introduce StateDescriptor and StateEvaluator for use with Rules

This commit is contained in:
Michael Zanetti 2014-06-09 04:28:38 +02:00
parent 21738b3907
commit 08223606ee
25 changed files with 817 additions and 240 deletions

6
debian/changelog vendored
View File

@ -1,3 +1,9 @@
guh (0.1.7) utopic; urgency=medium
* implement StateEvaluators
-- Michael Zanetti <micha@noneyet> Sun, 08 Jun 2014 23:27:31 +0200
guh (0.1.6) utopic; urgency=medium
* state changes auto generate events now

View File

@ -26,6 +26,7 @@ SOURCES += plugin/device.cpp \
types/paramtype.cpp \
types/param.cpp \
types/paramdescriptor.cpp \
types/statedescriptor.cpp
HEADERS += plugin/device.h \
plugin/deviceclass.h \
@ -45,5 +46,6 @@ HEADERS += plugin/device.h \
types/typeutils.h \
types/paramtype.h \
types/param.h \
types/paramdescriptor.h
types/paramdescriptor.h \
types/statedescriptor.h

View File

@ -146,7 +146,6 @@ bool Device::hasState(const StateTypeId &stateTypeId) const
/*! For convenience, this finds the \l{State} matching the given \a stateTypeId and returns the current valie in this Device. */
QVariant Device::stateValue(const StateTypeId &stateTypeId) const
{
qDebug() << "device has states:" << m_states.count();
foreach (const State &state, m_states) {
qDebug() << "checking" << stateTypeId << state.stateTypeId();
if (state.stateTypeId() == stateTypeId) {
@ -171,6 +170,16 @@ void Device::setStateValue(const StateTypeId &stateTypeId, const QVariant &value
qWarning() << "failed setting state for" << m_name;
}
State Device::state(const StateTypeId &stateTypeId) const
{
for (int i = 0; i < m_states.count(); ++i) {
if (m_states.at(i).stateTypeId() == stateTypeId) {
return m_states.at(i);
}
}
return State(StateTypeId(), DeviceId());
}
bool Device::setupComplete() const
{
return m_setupComplete;

View File

@ -45,18 +45,20 @@ public:
void setName(const QString &name);
QList<Param> params() const;
bool hasParam(const QString &paramName) const;
void setParams(const QList<Param> &params);
QVariant paramValue(const QString &paramName) const;
QList<State> states() const;
bool hasParam(const QString &paramName) const;
bool hasState(const StateTypeId &stateTypeId) const;
void setStates(const QList<State> &states);
bool hasState(const StateTypeId &stateTypeId) const;
QVariant stateValue(const StateTypeId &stateTypeId) const;
void setStateValue(const StateTypeId &stateTypeId, const QVariant &value);
State state(const StateTypeId &stateTypeId) const;
bool setupComplete() const;
signals:

View File

@ -32,13 +32,19 @@
/*! Constructs an EventDescriptor describing an Event.
*/
EventDescriptor::EventDescriptor(const EventTypeId &eventTypeId, const DeviceId &deviceId, const QList<ParamDescriptor> &paramDescriptors):
EventDescriptor::EventDescriptor(const EventDescriptorId &id, const EventTypeId &eventTypeId, const DeviceId &deviceId, const QList<ParamDescriptor> &paramDescriptors):
m_id(id),
m_eventTypeId(eventTypeId),
m_deviceId(deviceId),
m_paramDescriptors(paramDescriptors)
{
}
EventDescriptorId EventDescriptor::id() const
{
return m_id;
}
/*! Returns the id of the \l{EventType} which describes this Event.*/
EventTypeId EventDescriptor::eventTypeId() const
{
@ -98,33 +104,33 @@ bool EventDescriptor::operator ==(const Event &event) const
}
foreach (const ParamDescriptor &paramDescriptor, m_paramDescriptors) {
switch (paramDescriptor.operand()) {
case ParamDescriptor::OperandTypeEquals:
switch (paramDescriptor.operatorType()) {
case ValueOperatorEquals:
if (event.param(paramDescriptor.name()).value() != paramDescriptor.value()) {
return false;
}
break;
case ParamDescriptor::OperandTypeNotEquals:
case ValueOperatorNotEquals:
if (event.param(paramDescriptor.name()).value() == paramDescriptor.value()) {
return false;
}
break;
case ParamDescriptor::OperandTypeGreater:
case ValueOperatorGreater:
if (event.param(paramDescriptor.name()).value() <= paramDescriptor.value()) {
return false;
}
break;
case ParamDescriptor::OperandTypeGreaterOrEqual:
case ValueOperatorGreaterOrEqual:
if (event.param(paramDescriptor.name()).value() < paramDescriptor.value()) {
return false;
}
break;
case ParamDescriptor::OperandTypeLess:
case ValueOperatorLess:
if (event.param(paramDescriptor.name()).value() >= paramDescriptor.value()) {
return false;
}
break;
case ParamDescriptor::OperandTypeLessOrEqual:
case ValueOperatorLessOrEqual:
if (event.param(paramDescriptor.name()).value() < paramDescriptor.value()) {
return false;
}

View File

@ -30,7 +30,9 @@
class EventDescriptor
{
public:
EventDescriptor(const EventTypeId &eventTypeId, const DeviceId &deviceId, const QList<ParamDescriptor> &paramDescriptors = QList<ParamDescriptor>());
EventDescriptor(const EventDescriptorId &id, const EventTypeId &eventTypeId, const DeviceId &deviceId, const QList<ParamDescriptor> &paramDescriptors = QList<ParamDescriptor>());
EventDescriptorId id() const;
EventTypeId eventTypeId() const;
DeviceId deviceId() const;
@ -44,6 +46,7 @@ public:
bool operator ==(const Event &event) const;
private:
EventDescriptorId m_id;
EventTypeId m_eventTypeId;
DeviceId m_deviceId;
QList<ParamDescriptor> m_paramDescriptors;

View File

@ -20,17 +20,17 @@
ParamDescriptor::ParamDescriptor(const QString &name, const QVariant &value):
Param(name, value),
m_operand(OperandTypeEquals)
m_operatorType(ValueOperatorEquals)
{
}
ParamDescriptor::OperandType ParamDescriptor::operand() const
ValueOperator ParamDescriptor::operatorType() const
{
return m_operand;
return m_operatorType;
}
void ParamDescriptor::setOperand(ParamDescriptor::OperandType operand)
void ParamDescriptor::setOperatorType(ValueOperator operatorType)
{
m_operand = operand;
m_operatorType = operatorType;
}

View File

@ -20,25 +20,18 @@
#define PARAMDESCRIPTOR_H
#include "param.h"
#include "typeutils.h"
class ParamDescriptor : public Param
{
public:
enum OperandType {
OperandTypeEquals,
OperandTypeNotEquals,
OperandTypeLess,
OperandTypeGreater,
OperandTypeLessOrEqual,
OperandTypeGreaterOrEqual
};
ParamDescriptor(const QString &name, const QVariant &value = QVariant());
OperandType operand() const;
void setOperand(OperandType operand);
ValueOperator operatorType() const;
void setOperatorType(ValueOperator operatorType);
private:
OperandType m_operand;
ValueOperator m_operatorType;
};
#endif // PARAMDESCRIPTOR_H

View File

@ -0,0 +1,96 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* 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 "statedescriptor.h"
StateDescriptor::StateDescriptor():
m_id(StateDescriptorId::createStateDescriptorId()),
m_operatorType(ValueOperatorEquals)
{
}
StateDescriptor::StateDescriptor(const StateDescriptorId &id, const StateTypeId &stateTypeId, const DeviceId &deviceId, const QVariant &stateValue, ValueOperator operatorType):
m_id(id),
m_stateTypeId(stateTypeId),
m_deviceId(deviceId),
m_stateValue(stateValue),
m_operatorType(operatorType)
{
}
StateDescriptorId StateDescriptor::id() const
{
return m_id;
}
StateTypeId StateDescriptor::stateTypeId() const
{
return m_stateTypeId;
}
DeviceId StateDescriptor::deviceId() const
{
return m_deviceId;
}
QVariant StateDescriptor::stateValue() const
{
return m_stateValue;
}
ValueOperator StateDescriptor::operatorType() const
{
return m_operatorType;
}
bool StateDescriptor::operator ==(const StateDescriptor &other) const
{
return m_stateTypeId == other.stateTypeId() &&
m_deviceId == other.deviceId() &&
m_stateValue == other.stateValue() &&
m_operatorType == other.operatorType();
}
bool StateDescriptor::operator ==(const State &state) const
{
if ((m_stateTypeId != state.stateTypeId()) || (m_deviceId != state.deviceId())) {
return false;
}
switch (m_operatorType) {
case ValueOperatorEquals:
return m_stateValue == state.value();
case ValueOperatorGreater:
return m_stateValue > state.value();
case ValueOperatorGreaterOrEqual:
return m_stateValue >= state.value();
case ValueOperatorLess:
return m_stateValue < state.value();
case ValueOperatorLessOrEqual:
return m_stateValue <= state.value();
case ValueOperatorNotEquals:
return m_stateValue != state.value();
}
return false;
}
bool StateDescriptor::operator !=(const State &state) const
{
return !(operator==(state));
}

View File

@ -0,0 +1,58 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* 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 STATEDESCRIPTOR_H
#define STATEDESCRIPTOR_H
#include "typeutils.h"
#include "paramdescriptor.h"
#include "state.h"
#include <QString>
#include <QVariantList>
#include <QDebug>
class StateDescriptor
{
public:
StateDescriptor();
StateDescriptor(const StateDescriptorId &id, const StateTypeId &stateTypeId, const DeviceId &deviceId, const QVariant &stateValue, ValueOperator operatorType = ValueOperatorEquals);
StateDescriptorId id() const;
StateTypeId stateTypeId() const;
DeviceId deviceId() const;
QVariant stateValue() const;
ValueOperator operatorType() const;
bool operator ==(const StateDescriptor &other) const;
bool operator ==(const State &state) const;
bool operator !=(const State &state) const;
private:
StateDescriptorId m_id;
StateTypeId m_stateTypeId;
DeviceId m_deviceId;
QVariant m_stateValue;
ValueOperator m_operatorType;
};
QDebug operator<<(QDebug dbg, const StateDescriptor &eventDescriptor);
QDebug operator<<(QDebug dbg, const QList<StateDescriptor> &eventDescriptors);
#endif // STATEDESCRIPTOR_H

View File

@ -43,10 +43,28 @@ DECLARE_TYPE_ID(DeviceDescriptor)
DECLARE_TYPE_ID(EventType)
DECLARE_TYPE_ID(Event)
DECLARE_TYPE_ID(EventDescriptor)
DECLARE_TYPE_ID(StateType)
DECLARE_TYPE_ID(State)
DECLARE_TYPE_ID(StateDescriptor)
DECLARE_TYPE_ID(StateEvaluator)
DECLARE_TYPE_ID(ActionType)
DECLARE_TYPE_ID(Action)
DECLARE_TYPE_ID(Plugin)
DECLARE_TYPE_ID(Rule)
enum ValueOperator {
ValueOperatorEquals,
ValueOperatorNotEquals,
ValueOperatorLess,
ValueOperatorGreater,
ValueOperatorLessOrEqual,
ValueOperatorGreaterOrEqual
};
enum StateOperator {
StateOperatorAnd,
StateOperatorOr
};
#endif // TYPEUTILS_H

View File

@ -28,16 +28,18 @@ bool JsonTypes::s_initialized = false;
QString JsonTypes::s_lastError;
QVariantList JsonTypes::s_basicTypes;
QVariantList JsonTypes::s_ruleTypes;
QVariantList JsonTypes::s_stateOperatorTypes;
QVariantList JsonTypes::s_valueOperatorTypes;
QVariantList JsonTypes::s_createMethodTypes;
QVariantList JsonTypes::s_setupMethodTypes;
QVariantList JsonTypes::s_operandTypes;
QVariantMap JsonTypes::s_paramType;
QVariantMap JsonTypes::s_param;
QVariantMap JsonTypes::s_paramDescriptor;
QVariantMap JsonTypes::s_stateType;
QVariantMap JsonTypes::s_state;
QVariantMap JsonTypes::s_stateDescriptor;
QVariantMap JsonTypes::s_stateEvaluator;
QVariantMap JsonTypes::s_eventType;
QVariantMap JsonTypes::s_event;
QVariantMap JsonTypes::s_eventDescriptor;
@ -54,10 +56,10 @@ void JsonTypes::init()
{
// BasicTypes
s_basicTypes << "uuid" << "string" << "integer" << "double" << "bool";
s_ruleTypes << "RuleTypeMatchAll" << "RuleTypeMatchAny";
s_stateOperatorTypes << "StateOperatorAnd" << "StateOperatorOr";
s_valueOperatorTypes << "OperatorTypeEquals" << "OperatorTypeNotEquals" << "OperatorTypeLess" << "OperatorTypeGreater" << "OperatorTypeLessThan" << "OperatorTypeGreaterThan";
s_createMethodTypes << "CreateMethodUser" << "CreateMethodAuto" << "CreateMethodDiscovery";
s_setupMethodTypes << "SetupMethodJustAdd" << "SetupMethodDisplayPin" << "SetupMethodEnterPin" << "SetupMethodPushButton";
s_operandTypes << "OperandTypeEquals" << "OperandTypeNotEquals" << "OperandTypeLess" << "OperandTypeGreater" << "OperandTypeLessThan" << "OperandTypeGreaterThan";
// ParamType
s_paramType.insert("name", "string");
@ -73,7 +75,7 @@ void JsonTypes::init()
// ParamDescriptor
s_paramDescriptor.insert("name", "string");
s_paramDescriptor.insert("value", basicTypesRef());
s_paramDescriptor.insert("operand", operandTypesRef());
s_paramDescriptor.insert("operator", valueOperatorTypesRef());
// StateType
s_stateType.insert("id", "uuid");
@ -86,6 +88,19 @@ void JsonTypes::init()
s_state.insert("deviceId", "uuid");
s_state.insert("value", "variant");
// StateDescriptor
s_stateDescriptor.insert("id", "uuid");
s_stateDescriptor.insert("stateTypeId", "uuid");
s_stateDescriptor.insert("deviceId", "uuid");
s_stateDescriptor.insert("value", "variant");
s_stateDescriptor.insert("operator", valueOperatorTypesRef());
// StateEvaluator
s_stateEvaluator.insert("id", "uuid");
s_stateEvaluator.insert("o:stateDescriptor", stateDescriptorRef());
s_stateEvaluator.insert("o:childEvaluators", QVariantList() << stateEvaluatorRef());
s_stateEvaluator.insert("o:operator", stateOperatorTypesRef());
// EventType
s_eventType.insert("id", "uuid");
s_eventType.insert("name", "string");
@ -146,10 +161,9 @@ void JsonTypes::init()
// Rule
s_rule.insert("id", "uuid");
s_rule.insert("ruleType", ruleTypesRef());
s_rule.insert("eventDescriptors", QVariantList() << eventDescriptorRef());
s_rule.insert("actions", QVariantList() << actionRef());
s_rule.insert("states", QVariantList() << stateRef());
s_rule.insert("stateEvaluator", stateEvaluatorRef());
s_initialized = true;
}
@ -166,8 +180,11 @@ QVariantMap JsonTypes::allTypes()
allTypes.insert("ParamType", paramTypeDescription());
allTypes.insert("CreateMethodType", createMethodTypes());
allTypes.insert("SetupMethodType", setupMethodTypes());
allTypes.insert("OperandType", operandTypes());
allTypes.insert("ValueOperatorType", valueOperatorTypes());
allTypes.insert("StateOperatorType", stateOperatorTypes());
allTypes.insert("StateType", stateTypeDescription());
allTypes.insert("StateDescriptor", stateDescriptorDescription());
allTypes.insert("StateEvaluator", stateEvaluatorDescription());
allTypes.insert("Event", eventDescription());
allTypes.insert("EventType", eventTypeDescription());
allTypes.insert("EventDescriptor", eventDescriptorDescription());
@ -181,7 +198,6 @@ QVariantMap JsonTypes::allTypes()
allTypes.insert("Device", deviceDescription());
allTypes.insert("DeviceDescriptor", deviceDescriptorDescription());
allTypes.insert("Action", actionDescription());
allTypes.insert("RuleType", ruleTypes());
allTypes.insert("Rule", ruleDescription());
return allTypes;
}
@ -221,7 +237,7 @@ QVariantMap JsonTypes::packEventDescriptor(const EventDescriptor &eventDescripto
foreach (const ParamDescriptor &paramDescriptor, eventDescriptor.paramDescriptors()) {
params.append(packParamDescriptor(paramDescriptor));
}
variant.insert("params", params);
variant.insert("paramDescriptors", params);
return variant;
}
@ -261,6 +277,31 @@ QVariantMap JsonTypes::packStateType(const StateType &stateType)
return variantMap;
}
QVariantMap JsonTypes::packStateDescriptor(const StateDescriptor &stateDescriptor)
{
QVariantMap variantMap;
variantMap.insert("id", stateDescriptor.id().toString());
variantMap.insert("stateTypeId", stateDescriptor.stateTypeId().toString());
variantMap.insert("deviceId", stateDescriptor.deviceId().toString());
variantMap.insert("value", stateDescriptor.stateValue());
variantMap.insert("operator", valueOperatorTypes().at(stateDescriptor.operatorType()));
return variantMap;
}
QVariantMap JsonTypes::packStateEvaluator(const StateEvaluator &stateEvaluator)
{
QVariantMap variantMap;
variantMap.insert("id", stateEvaluator.id());
variantMap.insert("stateDescriptor", packStateDescriptor(stateEvaluator.stateDescriptor()));
QVariantList childEvaluators;
foreach (const StateEvaluator &childEvaluator, stateEvaluator.childEvaluators()) {
childEvaluators.append(packStateEvaluator(childEvaluator));
}
variantMap.insert("childEvaluators", childEvaluators);
return variantMap;
}
QVariantMap JsonTypes::packParam(const Param &param)
{
QVariantMap variantMap;
@ -273,7 +314,7 @@ QVariantMap JsonTypes::packParamDescriptor(const ParamDescriptor &paramDescripto
QVariantMap variantMap;
variantMap.insert("name", paramDescriptor.name());
variantMap.insert("value", paramDescriptor.value());
variantMap.insert("operand", s_operandTypes.at(paramDescriptor.operand()));
variantMap.insert("operator", s_valueOperatorTypes.at(paramDescriptor.operatorType()));
return variantMap;
}
@ -380,16 +421,12 @@ QVariantMap JsonTypes::packRule(const Rule &rule)
}
ruleMap.insert("eventDescriptors", eventDescriptorList);
ruleMap.insert("ruleType", s_ruleTypes.at(rule.ruleType()));
QVariantList actionList;
foreach (const Action &action, rule.actions()) {
actionList.append(JsonTypes::packAction(action));
}
ruleMap.insert("actions", actionList);
QVariantList states;
ruleMap.insert("states", states);
ruleMap.insert("stateEvaluator", JsonTypes::packStateEvaluator(rule.stateEvaluator()));
return ruleMap;
}
@ -412,19 +449,19 @@ QList<Param> JsonTypes::unpackParams(const QVariantList &paramList)
ParamDescriptor JsonTypes::unpackParamDescriptor(const QVariantMap &paramMap)
{
ParamDescriptor param(paramMap.value("name").toString(), paramMap.value("value"));
QString operandString = paramMap.value("operand").toString();
if (operandString == "OperandTypeEquals") {
param.setOperand(ParamDescriptor::OperandTypeEquals);
} else if (operandString == "OperandTypeNotEquals") {
param.setOperand(ParamDescriptor::OperandTypeNotEquals);
} else if (operandString == "OperandTypeLess") {
param.setOperand(ParamDescriptor::OperandTypeLess);
} else if (operandString == "OperandTypeGreater") {
param.setOperand(ParamDescriptor::OperandTypeGreater);
} else if (operandString == "OperandTypeLessOrEqual") {
param.setOperand(ParamDescriptor::OperandTypeLessOrEqual);
} else if (operandString == "OperandTypeGreaterOrEqual") {
param.setOperand(ParamDescriptor::OperandTypeGreaterOrEqual);
QString operatorString = paramMap.value("operator").toString();
if (operatorString == "ValueOperatorEquals") {
param.setOperatorType(ValueOperatorEquals);
} else if (operatorString == "ValueOperatorNotEquals") {
param.setOperatorType(ValueOperatorNotEquals);
} else if (operatorString == "ValueOperatorLess") {
param.setOperatorType(ValueOperatorLess);
} else if (operatorString == "ValueOperatorGreater") {
param.setOperatorType(ValueOperatorGreater);
} else if (operatorString == "ValueOperatorLessOrEqual") {
param.setOperatorType(ValueOperatorLessOrEqual);
} else if (operatorString == "ValueOperatorGreaterOrEqual") {
param.setOperatorType(ValueOperatorGreaterOrEqual);
}
return param;
}
@ -589,6 +626,18 @@ QPair<bool, QString> JsonTypes::validateVariant(const QVariant &templateVariant,
qDebug() << "state type not matching";
return result;
}
} else if (refName == stateEvaluatorRef()) {
QPair<bool, QString> result = validateMap(stateEvaluatorDescription(), variant.toMap());
if (!result.first) {
qDebug() << "stateEvaluator type not matching";
return result;
}
} else if (refName == stateDescriptorRef()) {
QPair<bool, QString> result = validateMap(stateDescriptorDescription(), variant.toMap());
if (!result.first) {
qDebug() << "stateDescriptor type not matching";
return result;
}
} else if (refName == pluginRef()) {
QPair<bool, QString> result = validateMap(pluginDescription(), variant.toMap());
if (!result.first) {
@ -601,16 +650,22 @@ QPair<bool, QString> JsonTypes::validateVariant(const QVariant &templateVariant,
qDebug() << "rule type not matching";
return result;
}
} else if (refName == eventDescriptorRef()) {
QPair<bool, QString> result = validateMap(eventDescriptorDescription(), variant.toMap());
if (!result.first) {
qDebug() << "evendescriptor not matching";
return result;
}
} else if (refName == basicTypesRef()) {
QPair<bool, QString> result = validateBasicType(variant);
if (!result.first) {
qDebug() << "value not allowed in" << basicTypesRef();
return result;
}
} else if (refName == ruleTypesRef()) {
QPair<bool, QString> result = validateRuleType(variant);
} else if (refName == stateOperatorTypesRef()) {
QPair<bool, QString> result = validateStateOperatorType(variant);
if (!result.first) {
qDebug() << "value not allowed in" << ruleTypesRef();
qDebug() << "value not allowed in" << stateOperatorTypesRef();
return result;
}
} else if (refName == createMethodTypesRef()) {
@ -625,10 +680,10 @@ QPair<bool, QString> JsonTypes::validateVariant(const QVariant &templateVariant,
qDebug() << "value not allowed in" << createMethodTypesRef();
return result;
}
} else if (refName == operandTypesRef()) {
QPair<bool, QString> result = validateOperandType(variant);
} else if (refName == valueOperatorTypesRef()) {
QPair<bool, QString> result = validateValueOperatorType(variant);
if (!result.first) {
qDebug() << QString("value %1 not allowed in %2").arg(variant.toString()).arg(operandTypesRef());
qDebug() << QString("value %1 not allowed in %2").arg(variant.toString()).arg(valueOperatorTypesRef());
return result;
}
} else {
@ -685,9 +740,9 @@ QPair<bool, QString> JsonTypes::validateBasicType(const QVariant &variant)
return report(false, QString("Error validating basic type %1.").arg(variant.toString()));
}
QPair<bool, QString> JsonTypes::validateRuleType(const QVariant &variant)
QPair<bool, QString> JsonTypes::validateStateOperatorType(const QVariant &variant)
{
return report(s_ruleTypes.contains(variant.toString()), QString("Unknown rules type %1").arg(variant.toString()));
return report(s_stateOperatorTypes.contains(variant.toString()), QString("Unknown state operator %1").arg(variant.toString()));
}
QPair<bool, QString> JsonTypes::validateCreateMethodType(const QVariant &variant)
@ -700,7 +755,7 @@ QPair<bool, QString> JsonTypes::validateSetupMethodType(const QVariant &variant)
return report(s_setupMethodTypes.contains(variant.toString()), QString("Unknwon setupMethod type %1").arg(variant.toString()));
}
QPair<bool, QString> JsonTypes::validateOperandType(const QVariant &variant)
QPair<bool, QString> JsonTypes::validateValueOperatorType(const QVariant &variant)
{
return report(s_operandTypes.contains(variant.toString()), QString("Unknown operand type %1").arg(variant.toString()));
return report(s_valueOperatorTypes.contains(variant.toString()), QString("Unknown value operator type %1").arg(variant.toString()));
}

View File

@ -65,15 +65,17 @@ public:
static QVariantMap allTypes();
DECLARE_TYPE(basicTypes, "BasicType")
DECLARE_TYPE(ruleTypes, "RuleType")
DECLARE_TYPE(stateOperatorTypes, "StateOperatorType")
DECLARE_TYPE(valueOperatorTypes, "ValueOperatorType")
DECLARE_TYPE(createMethodTypes, "CreateMethodType")
DECLARE_TYPE(setupMethodTypes, "SetupMethodType")
DECLARE_TYPE(operandTypes, "OperandType")
DECLARE_OBJECT(paramType, "ParamType")
DECLARE_OBJECT(param, "Param")
DECLARE_OBJECT(paramDescriptor, "ParamDescriptor")
DECLARE_OBJECT(stateType, "StateType")
DECLARE_OBJECT(stateDescriptor, "StateDescriptor")
DECLARE_OBJECT(state, "State")
DECLARE_OBJECT(stateEvaluator, "StateEvaluator")
DECLARE_OBJECT(eventType, "EventType")
DECLARE_OBJECT(event, "Event")
DECLARE_OBJECT(eventDescriptor, "EventDescriptor")
@ -92,6 +94,8 @@ public:
static QVariantMap packActionType(const ActionType &actionType);
static QVariantMap packAction(const Action &action);
static QVariantMap packStateType(const StateType &stateType);
static QVariantMap packStateDescriptor(const StateDescriptor &stateDescriptor);
static QVariantMap packStateEvaluator(const StateEvaluator &stateEvaluator);
static QVariantMap packParam(const Param &param);
static QVariantMap packParamType(const ParamType &paramType);
static QVariantMap packParamDescriptor(const ParamDescriptor &paramDescriptor);
@ -112,10 +116,10 @@ public:
static QPair<bool, QString> validateList(const QVariantList &templateList, const QVariantList &list);
static QPair<bool, QString> validateVariant(const QVariant &templateVariant, const QVariant &variant);
static QPair<bool, QString> validateBasicType(const QVariant &variant);
static QPair<bool, QString> validateRuleType(const QVariant &variant);
static QPair<bool, QString> validateStateOperatorType(const QVariant &variant);
static QPair<bool, QString> validateCreateMethodType(const QVariant &variant);
static QPair<bool, QString> validateSetupMethodType(const QVariant &variant);
static QPair<bool, QString> validateOperandType(const QVariant &variant);
static QPair<bool, QString> validateValueOperatorType(const QVariant &variant);
private:
static bool s_initialized;

View File

@ -46,12 +46,15 @@ RulesHandler::RulesHandler(QObject *parent) :
setParams("AddRule", params);
returns.insert("success", "bool");
returns.insert("errorMessage", "string");
returns.insert("o:ruleId", "uuid");
setReturns("AddRule", returns);
params.clear(); returns.clear();
setDescription("RemoveRule", "Remove a rule");
params.insert("ruleId", "uuid");
setParams("RemoveRule", params);
returns.insert("success", "bool");
returns.insert("errorMessage", "string");
setReturns("RemoveRule", returns);
}
@ -66,7 +69,6 @@ JsonReply* RulesHandler::GetRules(const QVariantMap &params)
QVariantList rulesList;
foreach (const Rule &rule, GuhCore::instance()->ruleEngine()->rules()) {
qDebug() << "got rule" << rule.id();
QVariantMap ruleMap = JsonTypes::packRule(rule);
rulesList.append(ruleMap);
}
@ -78,16 +80,15 @@ JsonReply* RulesHandler::GetRules(const QVariantMap &params)
JsonReply* RulesHandler::AddRule(const QVariantMap &params)
{
QVariantMap eventMap = params.value("event").toMap();
QVariantMap eventMap = params.value("eventDescriptor").toMap();
EventTypeId eventTypeId(eventMap.value("eventTypeId").toString());
DeviceId eventDeviceId(eventMap.value("deviceId").toString());
QList<ParamDescriptor> eventParams = JsonTypes::unpackParamDescriptors(eventMap.value("paramDescriptors").toList());
EventDescriptor eventDescriptor(eventTypeId, eventDeviceId, eventParams);
EventDescriptor eventDescriptor(EventDescriptorId::createEventDescriptorId(), eventTypeId, eventDeviceId, eventParams);
QList<Action> actions;
QVariantList actionList = params.value("actions").toList();
qDebug() << "got action list" << actionList.count();
foreach (const QVariant &actionVariant, actionList) {
QVariantMap actionMap = actionVariant.toMap();
Action action(ActionTypeId(actionMap.value("actionTypeId").toString()), DeviceId(actionMap.value("deviceId").toString()));
@ -102,10 +103,12 @@ JsonReply* RulesHandler::AddRule(const QVariantMap &params)
return createReply(returns);
}
switch(GuhCore::instance()->ruleEngine()->addRule(eventDescriptor, actions)) {
RuleId newRuleId = RuleId::createRuleId();
switch(GuhCore::instance()->ruleEngine()->addRule(newRuleId, eventDescriptor, actions)) {
case RuleEngine::RuleErrorNoError:
returns.insert("success", true);
returns.insert("errorMessage", "");
returns.insert("ruleId", newRuleId.toString());
break;
case RuleEngine::RuleErrorDeviceNotFound:
returns.insert("success", false);
@ -125,10 +128,11 @@ JsonReply* RulesHandler::AddRule(const QVariantMap &params)
JsonReply* RulesHandler::RemoveRule(const QVariantMap &params)
{
QVariantMap returns;
QUuid ruleId = params.value("ruleId").toUuid();
RuleId ruleId(params.value("ruleId").toString());
switch (GuhCore::instance()->ruleEngine()->removeRule(ruleId)) {
case RuleEngine::RuleErrorNoError:
returns.insert("success", true);
returns.insert("errorMessage", "");
break;
case RuleEngine::RuleErrorRuleNotFound:
returns.insert("success", false);

View File

@ -48,19 +48,23 @@
#include <QDebug>
/*! Constructs a Rule with the given \a id, \a eventDescriptor, \a states and \a actions. The ruleType will default to
\l{Rule::RuleTypeAll}.*/
Rule::Rule(const QUuid &id, const EventDescriptor &eventDescriptor, const QList<State> &states, const QList<Action> &actions):
/*! Constructs an empty, invalid rule. */
Rule::Rule()
{
}
/*! Constructs a Rule with the given \a id, \a eventDescriptor, \a states and \a actions.*/
Rule::Rule(const RuleId &id, const QList<EventDescriptor> &eventDescriptorList, const StateEvaluator &stateEvaluator, const QList<Action> &actions):
m_id(id),
m_eventDescriptors(QList<EventDescriptor>() << eventDescriptor),
m_states(states),
m_actions(actions),
m_ruleType(RuleTypeAll)
m_eventDescriptors(eventDescriptorList),
m_stateEvaluator(stateEvaluator),
m_actions(actions)
{
}
/*! Returns the id or the Rule. */
QUuid Rule::id() const
RuleId Rule::id() const
{
return m_id;
}
@ -71,10 +75,10 @@ QList<EventDescriptor> Rule::eventDescriptors() const
return m_eventDescriptors;
}
/*! Returns the \l{State}{States} that need to be matching in order for this to Rule apply. */
QList<State> Rule::states() const
/*! Returns the \l{StateEvaluator} that needs to evaluate successfully in order for this to Rule apply. */
StateEvaluator Rule::stateEvaluator() const
{
return m_states;
return m_stateEvaluator;
}
/*! Returns the \l{Action}{Actions} to be executed when this Rule is matched and states match. */
@ -82,15 +86,3 @@ QList<Action> Rule::actions() const
{
return m_actions;
}
/*! Returns the type of the rule. This defines how states are compared. The default is \l{Rule::RuleTypeAll}.*/
Rule::RuleType Rule::ruleType() const
{
return m_ruleType;
}
/*! Set the type of the rule to \a ruleType. This defines how states are compared. The default is \l{Rule::RuleTypeAll}.*/
void Rule::setRuleType(Rule::RuleType ruleType)
{
m_ruleType = ruleType;
}

View File

@ -29,28 +29,19 @@
class Rule
{
public:
enum RuleType {
RuleTypeAll,
RuleTypeAny
};
Rule();
Rule(const RuleId &id, const QList<EventDescriptor> &eventDescriptorList, const StateEvaluator &stateEvaluator, const QList<Action> &actions);
Rule(const QUuid &id, const EventDescriptor &eventDescriptor, const QList<State> &states, const QList<Action> &actions);
QUuid id() const;
RuleId id() const;
QList<EventDescriptor> eventDescriptors() const;
QList<State> states() const;
StateEvaluator stateEvaluator() const;
QList<Action> actions() const;
RuleType ruleType() const;
void setRuleType(RuleType ruleType);
private:
QUuid m_id;
RuleId m_id;
QList<EventDescriptor> m_eventDescriptors;
QList<State> m_states;
StateEvaluator stateEvaluator;
StateEvaluator m_stateEvaluator;
QList<Action> m_actions;
RuleType m_ruleType;
};
#endif // RULE_H

View File

@ -79,32 +79,36 @@ RuleEngine::RuleEngine(QObject *parent) :
settings.beginGroup(idString);
settings.beginGroup("event");
EventTypeId eventTypeId(settings.value("eventTypeId").toString());
DeviceId deviceId(settings.value("deviceId").toString());
QList<ParamDescriptor> params;
foreach (QString groupName, settings.childGroups()) {
if (groupName.startsWith("ParamDescriptor-")) {
settings.beginGroup(groupName);
ParamDescriptor paramDescriptor(groupName.remove(QRegExp("^ParamDescriptor-")), settings.value("value"));
paramDescriptor.setOperand((ParamDescriptor::OperandType)settings.value("operand").toInt());
params.append(paramDescriptor);
QList<EventDescriptor> eventDescriptorList;
settings.beginGroup("events");
foreach (QString eventGroupName, settings.childGroups()) {
if (eventGroupName.startsWith("EventDescriptor-")) {
settings.beginGroup(eventGroupName);
EventDescriptorId eventDescriptorId(eventGroupName.remove(QRegExp("^EventDescriptor-")));
EventTypeId eventTypeId(settings.value("eventTypeId").toString());
DeviceId deviceId(settings.value("deviceId").toString());
QList<ParamDescriptor> params;
foreach (QString groupName, settings.childGroups()) {
if (groupName.startsWith("ParamDescriptor-")) {
settings.beginGroup(groupName);
ParamDescriptor paramDescriptor(groupName.remove(QRegExp("^ParamDescriptor-")), settings.value("value"));
paramDescriptor.setOperatorType((ValueOperator)settings.value("operator").toInt());
params.append(paramDescriptor);
settings.endGroup();
}
}
EventDescriptor eventDescriptor(eventDescriptorId, eventTypeId, deviceId, params);
eventDescriptorList.append(eventDescriptor);
settings.endGroup();
}
}
EventDescriptor eventDescriptor(eventTypeId, deviceId, params);
settings.endGroup();
settings.beginGroup("states");
QList<State> states;
foreach (const QString &stateTypeIdString, settings.childGroups()) {
settings.beginGroup(stateTypeIdString);
State state(StateTypeId(stateTypeIdString), DeviceId(settings.value("deviceId").toString()));
state.setValue(settings.value("value"));
settings.endGroup();
states.append(state);
}
settings.endGroup();
StateEvaluator stateEvaluator = StateEvaluator::loadFromSettings(settings, "stateEvaluator");
settings.beginGroup("actions");
QList<Action> actions;
@ -129,8 +133,8 @@ RuleEngine::RuleEngine(QObject *parent) :
settings.endGroup();
Rule rule = Rule(QUuid(idString), eventDescriptor, states, actions);
m_rules.append(rule);
// Rule rule = Rule(RuleId(idString), eventDescriptorList, states, actions);
// m_rules.append(rule);
}
}
@ -146,23 +150,8 @@ QList<Action> RuleEngine::evaluateEvent(const Event &event)
for (int i = 0; i < m_rules.count(); ++i) {
qDebug() << "evaluating rule" << i << m_rules.at(i).eventDescriptors();
if (containsEvent(m_rules.at(i), event)) {
bool statesMatching = true;
qDebug() << "checking states:" << m_rules.at(i).states();
foreach (const State &state, m_rules.at(i).states()) {
Device *device = GuhCore::instance()->deviceManager()->findConfiguredDevice(state.deviceId());
if (!device) {
qWarning() << "Device referenced in rule cannot be found";
break;
}
if (state.value() != device->stateValue(state.stateTypeId())) {
qDebug() << "State value not matching:" << state.value() << device->stateValue(state.stateTypeId());
statesMatching = false;
break;
}
}
qDebug() << "states matching" << statesMatching;
if (statesMatching) {
if (m_rules.at(i).stateEvaluator().evaluate()) {
qDebug() << "states matching!";
actions.append(m_rules.at(i).actions());
}
}
@ -173,60 +162,86 @@ QList<Action> RuleEngine::evaluateEvent(const Event &event)
/*! Add a new \l{Rule} with the given \a event and \a actions to the engine.
For convenience, this creates a Rule without any \l{State} comparison. */
RuleEngine::RuleError RuleEngine::addRule(const EventDescriptor &eventDescriptor, const QList<Action> &actions)
RuleEngine::RuleError RuleEngine::addRule(const RuleId &ruleId, const EventDescriptor &eventDescriptor, const QList<Action> &actions)
{
return addRule(eventDescriptor, QList<State>(), actions);
QList<EventDescriptor> eventDescriptorList;
eventDescriptorList.append(eventDescriptor);
return addRule(ruleId, eventDescriptorList, StateEvaluator(StateEvaluatorId::createStateEvaluatorId()), actions);
}
/*! Add a new \l{Rule} with the given \a event, \a states and \a actions to the engine. */
RuleEngine::RuleError RuleEngine::addRule(const EventDescriptor &eventDescriptor, const QList<State> &states, const QList<Action> &actions)
RuleEngine::RuleError RuleEngine::addRule(const RuleId &ruleId, const QList<EventDescriptor> &eventDescriptorList, const StateEvaluator &stateEvaluator, const QList<Action> &actions)
{
Device *device = GuhCore::instance()->deviceManager()->findConfiguredDevice(eventDescriptor.deviceId());
if (!device) {
qWarning() << "Cannot create rule. No configured device for eventTypeId" << eventDescriptor.eventTypeId();
return RuleErrorDeviceNotFound;
if (ruleId.isNull()) {
return RuleErrorInvalidRuleId;
}
DeviceClass deviceClass = GuhCore::instance()->deviceManager()->findDeviceClass(device->deviceClassId());
qDebug() << "found deviceClass" << deviceClass.name();
if (!findRule(ruleId).id().isNull()) {
qWarning() << "Already have a rule with this id!";
return RuleErrorInvalidRuleId;
}
foreach (const EventDescriptor &eventDescriptor, eventDescriptorList) {
Device *device = GuhCore::instance()->deviceManager()->findConfiguredDevice(eventDescriptor.deviceId());
if (!device) {
qWarning() << "Cannot create rule. No configured device for eventTypeId" << eventDescriptor.eventTypeId();
return RuleErrorDeviceNotFound;
}
DeviceClass deviceClass = GuhCore::instance()->deviceManager()->findDeviceClass(device->deviceClassId());
bool eventTypeFound = false;
foreach (const EventType &eventType, deviceClass.eventTypes()) {
if (eventType.id() == eventDescriptor.eventTypeId()) {
eventTypeFound = true;
bool eventTypeFound = false;
foreach (const EventType &eventType, deviceClass.eventTypes()) {
if (eventType.id() == eventDescriptor.eventTypeId()) {
eventTypeFound = true;
}
}
if (!eventTypeFound) {
qWarning() << "Cannot create rule. Device " + device->name() + " has no event type:" << eventDescriptor.eventTypeId();
return RuleErrorEventTypeNotFound;
}
}
if (!eventTypeFound) {
qWarning() << "Cannot create rule. Device " + device->name() + " has no event type:" << eventDescriptor.eventTypeId();
return RuleErrorEventTypeNotFound;
foreach (const Action &action, actions) {
Device *device = GuhCore::instance()->deviceManager()->findConfiguredDevice(action.deviceId());
if (!device) {
qWarning() << "Cannot create rule. No configured device for actionTypeId" << action.actionTypeId();
return RuleErrorDeviceNotFound;
}
DeviceClass deviceClass = GuhCore::instance()->deviceManager()->findDeviceClass(device->deviceClassId());
bool actionTypeFound = false;
foreach (const ActionType &actionType, deviceClass.actionTypes()) {
if (actionType.id() == action.actionTypeId()) {
actionTypeFound = true;
}
}
if (!actionTypeFound) {
qWarning() << "Cannot create rule. Device " + device->name() + " has no action type:" << action.actionTypeId();
return RuleErrorActionTypeNotFound;
}
}
Rule rule = Rule(QUuid::createUuid(), eventDescriptor, states, actions);
Rule rule = Rule(ruleId, eventDescriptorList, stateEvaluator, actions);
m_rules.append(rule);
emit ruleAdded(rule.id());
QSettings settings(m_settingsFile);
settings.beginGroup(rule.id().toString());
settings.beginGroup("event");
settings.setValue("eventTypeId", eventDescriptor.eventTypeId());
settings.setValue("deviceId", eventDescriptor.deviceId());
foreach (const ParamDescriptor &paramDescriptor, eventDescriptor.paramDescriptors()) {
settings.beginGroup("ParamDescriptor-" + paramDescriptor.name());
settings.setValue("value", paramDescriptor.value());
settings.setValue("operand", paramDescriptor.operand());
settings.beginGroup("events");
foreach (const EventDescriptor &eventDescriptor, eventDescriptorList) {
settings.beginGroup("EventDescriptor-" + eventDescriptor.id().toString());
settings.setValue("deviceId", eventDescriptor.deviceId().toString());
settings.setValue("eventTypeId", eventDescriptor.eventTypeId());
foreach (const ParamDescriptor &paramDescriptor, eventDescriptor.paramDescriptors()) {
settings.beginGroup("ParamDescriptor-" + paramDescriptor.name());
settings.setValue("value", paramDescriptor.value());
settings.setValue("operator", paramDescriptor.operatorType());
settings.endGroup();
}
settings.endGroup();
}
settings.endGroup();
settings.beginGroup("states");
foreach (const State &state, states) {
settings.beginGroup(state.stateTypeId().toString());
settings.setValue("deviceId", state.deviceId());
settings.setValue("value", state.value());
settings.endGroup();
}
settings.endGroup();
stateEvaluator.dumpToSettings(settings, "stateEvaluator");
settings.beginGroup("actions");
foreach (const Action &action, rule.actions()) {
@ -256,7 +271,7 @@ QList<Rule> RuleEngine::rules() const
/*! Removes the \l{Rule} with the given \a ruleId from the Engine.
Returns \l{RuleEngine::RuleError} which describes whether the operation
was successful or not. */
RuleEngine::RuleError RuleEngine::removeRule(const QUuid &ruleId)
RuleEngine::RuleError RuleEngine::removeRule(const RuleId &ruleId)
{
for (int i = 0; i < m_rules.count(); ++i) {
Rule rule = m_rules.at(i);
@ -276,6 +291,16 @@ RuleEngine::RuleError RuleEngine::removeRule(const QUuid &ruleId)
return RuleErrorRuleNotFound;
}
Rule RuleEngine::findRule(const RuleId &ruleId)
{
foreach (const Rule &rule, m_rules) {
if (rule.id() == ruleId) {
return rule;
}
}
return Rule();
}
bool RuleEngine::containsEvent(const Rule &rule, const Event &event)
{
foreach (const EventDescriptor &eventDescriptor, rule.eventDescriptors()) {

View File

@ -21,6 +21,7 @@
#include "rule.h"
#include "types/event.h"
#include "stateevaluator.h"
#include <QObject>
#include <QList>
@ -32,24 +33,28 @@ class RuleEngine : public QObject
public:
enum RuleError {
RuleErrorNoError,
RuleErrorInvalidRuleId,
RuleErrorRuleNotFound,
RuleErrorDeviceNotFound,
RuleErrorEventTypeNotFound
RuleErrorEventTypeNotFound,
RuleErrorActionTypeNotFound
};
explicit RuleEngine(QObject *parent = 0);
QList<Action> evaluateEvent(const Event &event);
RuleError addRule(const EventDescriptor &eventDescriptor, const QList<Action> &actions);
RuleError addRule(const EventDescriptor &eventDescriptor, const QList<State> &states, const QList<Action> &actions);
RuleError addRule(const RuleId &ruleId, const EventDescriptor &eventDescriptor, const QList<Action> &actions);
RuleError addRule(const RuleId &ruleId, const QList<EventDescriptor> &eventDescriptorList, const StateEvaluator &stateEvaluator, const QList<Action> &actions);
QList<Rule> rules() const;
RuleError removeRule(const QUuid &ruleId);
RuleError removeRule(const RuleId &ruleId);
Rule findRule(const RuleId &ruleId);
signals:
void ruleAdded(const QUuid &ruleId);
void ruleRemoved(const QUuid &ruleId);
void ruleAdded(const RuleId &ruleId);
void ruleRemoved(const RuleId &ruleId);
private:
bool containsEvent(const Rule &rule, const Event &event);

View File

@ -17,9 +17,141 @@
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include "stateevaluator.h"
#include "guhcore.h"
#include "devicemanager.h"
StateEvaluator::StateEvaluator()
{
}
StateEvaluator::StateEvaluator(const StateEvaluatorId &id, const StateDescriptor &statedescriptor):
m_id(id),
m_stateDescriptor(statedescriptor)
{
}
StateEvaluator::StateEvaluator(const StateEvaluatorId &id, QList<StateEvaluator> childEvaluators, StateOperator stateOperator):
m_id(id),
m_childEvaluators(childEvaluators),
m_operatorType(stateOperator),
m_stateDescriptor()
{
}
StateEvaluatorId StateEvaluator::id() const
{
return m_id;
}
StateDescriptor StateEvaluator::stateDescriptor() const
{
return m_stateDescriptor;
}
QList<StateEvaluator> StateEvaluator::childEvaluators() const
{
return m_childEvaluators;
}
void StateEvaluator::setChildEvaluators(const QList<StateEvaluator> &stateEvaluators)
{
m_childEvaluators = stateEvaluators;
}
void StateEvaluator::appendEvaluator(const StateEvaluator &stateEvaluator)
{
m_childEvaluators.append(stateEvaluator);
}
StateOperator StateEvaluator::operatorType() const
{
return m_operatorType;
}
void StateEvaluator::setOperatorType(StateOperator operatorType)
{
m_operatorType = operatorType;
}
bool StateEvaluator::evaluate() const
{
if (!m_stateDescriptor.stateTypeId().isNull() && !m_stateDescriptor.deviceId().isNull()) {
Device *device = GuhCore::instance()->deviceManager()->findConfiguredDevice(m_stateDescriptor.deviceId());
if (!device) {
qWarning() << "Device not existing!";
return false;
}
if (device->hasState(m_stateDescriptor.stateTypeId())) {
qWarning() << "Device found, but it does not appear to have such a state!";
return false;
}
if (m_stateDescriptor != device->state(m_stateDescriptor.stateTypeId())) {
// state not matching
return false;
}
}
foreach (const StateEvaluator &stateEvaluator, m_childEvaluators) {
if (!stateEvaluator.evaluate()) {
return false;
}
}
return true;
}
void StateEvaluator::dumpToSettings(QSettings &settings, const QString &groupName) const
{
settings.beginGroup(groupName);
settings.setValue("id", m_id.toString());
settings.beginGroup("stateDescriptor");
settings.setValue("stateDescriptorId", m_stateDescriptor.id().toString());
settings.setValue("stateTypeId", m_stateDescriptor.stateTypeId().toString());
settings.setValue("deviceId", m_stateDescriptor.deviceId().toString());
settings.setValue("value", m_stateDescriptor.stateValue());
settings.setValue("operator", m_stateDescriptor.operatorType());
settings.endGroup();
settings.setValue("operator", m_operatorType);
settings.beginGroup("childEvaluators");
foreach (const StateEvaluator &evaluator, m_childEvaluators) {
evaluator.dumpToSettings(settings, "stateEvaluator-" + evaluator.id().toString());
}
settings.endGroup();
settings.endGroup();
}
StateEvaluator StateEvaluator::loadFromSettings(QSettings &settings, const QString &groupName)
{
settings.beginGroup(groupName);
StateEvaluatorId id(settings.value("id").toString());
settings.beginGroup("stateDescriptor");
StateDescriptorId stateDescriptorId(settings.value("stateDescriptorId").toString());
StateTypeId stateTypeId(settings.value("stateTypeId").toString());
DeviceId deviceId(settings.value("deviceId").toString());
QVariant stateValue = settings.value("value");
ValueOperator valueOperator = (ValueOperator)settings.value("operator").toInt();
StateDescriptor stateDescriptor(stateDescriptorId, stateTypeId, deviceId, stateValue, valueOperator);
settings.endGroup();
StateEvaluator ret(id, stateDescriptor);
ret.setOperatorType((StateOperator)settings.value("operator").toInt());
settings.beginGroup("childEvaluators");
foreach (const QString &evaluatorGroup, settings.childGroups()) {
settings.beginGroup(evaluatorGroup);
ret.appendEvaluator(StateEvaluator::loadFromSettings(settings, evaluatorGroup));
settings.endGroup();
}
settings.endGroup();
settings.endGroup();
return ret;
}

View File

@ -20,31 +20,44 @@
#define STATEEVALUATOR_H
#include "types/state.h"
#include "types/statedescriptor.h"
//class EvaluatorEntry
//{
//public:
// EvaluatorEntry();
// QUuid stateTypeId;
// QUuid deviceId;
//// Rule::Operator operation;
// QVariant value;
//};
//class EvaluatorChain
//{
//};
#include <QSettings>
class StateEvaluator
{
public:
enum OperatorType {
OperatorTypeAnd,
OperatorTypeOr
};
StateEvaluator();
StateEvaluator(const StateEvaluatorId &id, const StateDescriptor &statedescriptor);
StateEvaluator(const StateEvaluatorId &id, QList<StateEvaluator> childEvaluators = QList<StateEvaluator>(), StateOperator stateOperator = StateOperatorAnd);
StateEvaluatorId id() const;
StateDescriptor stateDescriptor() const;
QList<StateEvaluator> childEvaluators() const;
void setChildEvaluators(const QList<StateEvaluator> &childEvaluators);
void appendEvaluator(const StateEvaluator &stateEvaluator);
StateOperator operatorType() const;
void setOperatorType(StateOperator operatorType);
bool evaluate() const;
void dumpToSettings(QSettings &settings, const QString &groupName) const;
static StateEvaluator loadFromSettings(QSettings &settings, const QString &groupPrefix);
private:
// EvaluatorEntry m_entry;
StateEvaluatorId m_id;
StateDescriptor m_stateDescriptor;
QList<StateEvaluator> m_childEvaluators;
StateOperator m_operatorType;
};

View File

@ -1,4 +1,4 @@
0.1.6
0.1.7
{
"methods": {
"Actions.ExecuteAction": {
@ -223,6 +223,7 @@
},
"returns": {
"errorMessage": "string",
"o:ruleId": "uuid",
"success": "bool"
}
},
@ -242,6 +243,8 @@
"ruleId": "uuid"
},
"returns": {
"errorMessage": "string",
"success": "bool"
}
}
},
@ -345,21 +348,13 @@
"$ref:ParamType"
]
},
"OperandType": [
"OperandTypeEquals",
"OperandTypeNotEquals",
"OperandTypeLess",
"OperandTypeGreater",
"OperandTypeLessThan",
"OperandTypeGreaterThan"
],
"Param": {
"name": "string",
"value": "$ref:BasicType"
},
"ParamDescriptor": {
"name": "string",
"operand": "$ref:OperandType",
"operator": "$ref:ValueOperatorType",
"value": "$ref:BasicType"
},
"ParamType": {
@ -384,15 +379,8 @@
"$ref:EventDescriptor"
],
"id": "uuid",
"ruleType": "$ref:RuleType",
"states": [
"$ref:State"
]
"stateEvaluator": "$ref:StateEvaluator"
},
"RuleType": [
"RuleTypeMatchAll",
"RuleTypeMatchAny"
],
"SetupMethodType": [
"SetupMethodJustAdd",
"SetupMethodDisplayPin",
@ -404,12 +392,39 @@
"stateTypeId": "uuid",
"value": "variant"
},
"StateDescriptor": {
"deviceId": "uuid",
"id": "uuid",
"operator": "$ref:ValueOperatorType",
"stateTypeId": "uuid",
"value": "variant"
},
"StateEvaluator": {
"id": "uuid",
"o:childEvaluators": [
"$ref:StateEvaluator"
],
"o:operator": "$ref:StateOperatorType",
"o:stateDescriptor": "$ref:StateDescriptor"
},
"StateOperatorType": [
"StateOperatorAnd",
"StateOperatorOr"
],
"StateType": {
"defaultValue": "variant",
"id": "uuid",
"name": "string",
"type": "$ref:BasicType"
},
"ValueOperatorType": [
"OperatorTypeEquals",
"OperatorTypeNotEquals",
"OperatorTypeLess",
"OperatorTypeGreater",
"OperatorTypeLessThan",
"OperatorTypeGreaterThan"
],
"Vendor": {
"id": "uuid",
"name": "string"

View File

@ -1,2 +1,2 @@
TEMPLATE=subdirs
SUBDIRS=versioning devices jsonrpc events states actions
SUBDIRS=versioning devices jsonrpc events states actions rules

View File

@ -47,8 +47,6 @@ private slots:
void stateChangeEmitsNotifications();
void getRules();
private:
QStringList extractRefs(const QVariant &variant);
@ -252,12 +250,6 @@ void TestJSONRPC::stateChangeEmitsNotifications()
}
void TestJSONRPC::getRules()
{
QVariant response = injectAndWait("Rules.GetRules", QVariantMap());
qDebug() << "got rules response" << response;
}
#include "testjsonrpc.moc"
QTEST_MAIN(TestJSONRPC)

View File

@ -0,0 +1,5 @@
include(../../../guh.pri)
include(../autotests.pri)
TARGET = rules
SOURCES += testrules.cpp

View File

@ -0,0 +1,151 @@
/****************************************************************************
* *
* 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 "guhtestbase.h"
#include "guhcore.h"
#include "devicemanager.h"
#include "mocktcpserver.h"
#include <QtTest/QtTest>
#include <QCoreApplication>
#include <QTcpSocket>
#include <QNetworkAccessManager>
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QCoreApplication>
class TestRules: public GuhTestBase
{
Q_OBJECT
private slots:
void addRules_data();
void addRules();
void getStateValue_data();
void getStateValue();
};
void TestRules::addRules_data()
{
QVariantMap validAction;
validAction.insert("actionTypeId", mockActionIdNoParams);
validAction.insert("deviceId", m_mockDeviceId);
validAction.insert("params", QVariantList());
QVariantMap invalidAction;
invalidAction.insert("actionTypeId", ActionTypeId());
invalidAction.insert("deviceId", m_mockDeviceId);
invalidAction.insert("params", QVariantList());
QVariantMap validEventDescriptor;
validEventDescriptor.insert("eventTypeId", mockEvent1Id);
validEventDescriptor.insert("deviceId", m_mockDeviceId);
validEventDescriptor.insert("paramDescriptors", QVariantList());
QVariantMap invalidEventDescriptor;
invalidEventDescriptor.insert("eventTypeId", mockEvent1Id);
invalidEventDescriptor.insert("deviceId", DeviceId());
invalidEventDescriptor.insert("paramDescriptors", QVariantList());
QTest::addColumn<QVariantMap>("action1");
QTest::addColumn<QVariantMap>("eventDescriptor1");
QTest::addColumn<bool>("success");
QTest::newRow("valid rule") << validAction << validEventDescriptor << true;
QTest::newRow("invalid action") << invalidAction << validEventDescriptor << false;
QTest::newRow("invalid event descriptor") << validAction << invalidEventDescriptor << false;
}
void TestRules::addRules()
{
QFETCH(QVariantMap, action1);
QFETCH(QVariantMap, eventDescriptor1);
QFETCH(bool, success);
QVariantMap params;
QVariantList actions;
actions.append(action1);
params.insert("actions", actions);
params.insert("eventDescriptor", eventDescriptor1);
QVariant response = injectAndWait("Rules.AddRule", params);
RuleId newRuleId = RuleId(response.toMap().value("params").toMap().value("ruleId").toString());
verifySuccess(response, success);
response = injectAndWait("Rules.GetRules");
QVariantList rules = response.toMap().value("params").toMap().value("rules").toList();
if (!success) {
QVERIFY2(rules.count() == 0, "There should be no rules.");
return;
}
QVERIFY2(rules.count() == 1, "There should be exactly one rule");
QCOMPARE(RuleId(rules.first().toMap().value("id").toString()), newRuleId);
QVariantList eventDescriptors = rules.first().toMap().value("eventDescriptors").toList();
QVERIFY2(eventDescriptors.count() == 1, "There shoud be exactly one eventDescriptor");
QVERIFY2(eventDescriptors.first().toMap() == eventDescriptor1, "Event descriptor doesn't match");
QVariantList replyActions = rules.first().toMap().value("actions").toList();
QVERIFY2(actions == replyActions, "Actions don't match");
params.clear();
params.insert("ruleId", newRuleId);
response = injectAndWait("Rules.RemoveRule", params);
verifySuccess(response, true);
response = injectAndWait("Rules.GetRules");
rules = response.toMap().value("params").toMap().value("rules").toList();
QVERIFY2(rules.count() == 0, "There should be no rules.");
}
void TestRules::getStateValue_data()
{
QList<Device*> devices = GuhCore::instance()->deviceManager()->findConfiguredDevices(mockDeviceClassId);
QVERIFY2(devices.count() > 0, "There needs to be at least one configured Mock Device for this test");
Device *device = devices.first();
QTest::addColumn<DeviceId>("deviceId");
QTest::addColumn<StateTypeId>("stateTypeId");
QTest::addColumn<bool>("success");
QTest::newRow("existing state") << device->id() << mockIntStateId << true;
QTest::newRow("invalid device") << DeviceId::createDeviceId() << mockIntStateId << false;
QTest::newRow("invalid statetype") << device->id() << StateTypeId::createStateTypeId() << false;
}
void TestRules::getStateValue()
{
QFETCH(DeviceId, deviceId);
QFETCH(StateTypeId, stateTypeId);
QFETCH(bool, success);
QVariantMap params;
params.insert("deviceId", deviceId.toString());
params.insert("stateTypeId", stateTypeId.toString());
QVariant response = injectAndWait("Devices.GetStateValue", params);
verifySuccess(response, success);
}
#include "testrules.moc"
QTEST_MAIN(TestRules)