From 6bd8983ec2f7443cd89ebaafd70380d29b7764b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20St=C3=BCrz?= Date: Wed, 11 Mar 2015 21:39:43 +0100 Subject: [PATCH] added RuleAction and RuleActionParam to RuleEngine --- libguh/libguh.pro | 2 + libguh/types/ruleaction.cpp | 89 +++++++++++++++++++++ libguh/types/ruleaction.h | 36 +++++++++ libguh/types/ruleactionparam.cpp | 131 ++++++++++++++++++++++++++----- libguh/types/ruleactionparam.h | 34 ++++++-- server/guhcore.cpp | 38 +++++++-- server/guhcore.h | 2 +- server/jsonrpc/jsontypes.cpp | 73 ++++++++++++++--- server/jsonrpc/jsontypes.h | 7 ++ server/jsonrpc/ruleshandler.cpp | 50 +++++++++--- server/jsonrpc/ruleshandler.h | 1 + server/rule.cpp | 20 ++--- server/rule.h | 16 ++-- server/ruleengine.cpp | 62 +++++++-------- server/ruleengine.h | 7 +- 15 files changed, 466 insertions(+), 102 deletions(-) create mode 100644 libguh/types/ruleaction.cpp create mode 100644 libguh/types/ruleaction.h diff --git a/libguh/libguh.pro b/libguh/libguh.pro index 8da0ac89..cd9fed05 100644 --- a/libguh/libguh.pro +++ b/libguh/libguh.pro @@ -34,6 +34,7 @@ SOURCES += plugin/device.cpp \ types/paramtype.cpp \ types/param.cpp \ types/paramdescriptor.cpp \ + types/ruleaction.cpp \ types/ruleactionparam.cpp \ types/statedescriptor.cpp \ network/networkmanager.cpp \ @@ -65,6 +66,7 @@ HEADERS += plugin/device.h \ types/paramtype.h \ types/param.h \ types/paramdescriptor.h \ + types/ruleaction.h \ types/ruleactionparam.h \ types/statedescriptor.h \ typeutils.h \ diff --git a/libguh/types/ruleaction.cpp b/libguh/types/ruleaction.cpp new file mode 100644 index 00000000..150b6c86 --- /dev/null +++ b/libguh/types/ruleaction.cpp @@ -0,0 +1,89 @@ +#include "ruleaction.h" + +RuleAction::RuleAction(const ActionTypeId &actionTypeId, const DeviceId &deviceId) : + m_id(ActionId::createActionId()), + m_actionTypeId(actionTypeId), + m_deviceId(deviceId) +{ + +} + +RuleAction::RuleAction(const RuleAction &other) : + m_id(other.id()), + m_actionTypeId(other.actionTypeId()), + m_deviceId(other.deviceId()), + m_ruleActionParams(other.ruleActionParams()) +{ + +} + +ActionId RuleAction::id() const +{ + return m_id; +} + +bool RuleAction::isValid() const +{ + return !m_actionTypeId.isNull() && !m_deviceId.isNull(); +} + +bool RuleAction::isEventBased() const +{ + foreach (const RuleActionParam ¶m, m_ruleActionParams) { + if (param.eventTypeId() != EventTypeId()) { + return true; + } + } + return false; +} + +Action RuleAction::toAction() const +{ + Action action(m_actionTypeId, m_deviceId); + ParamList params; + foreach (const RuleActionParam &ruleActionParam, m_ruleActionParams) { + Param param; + param.setName(ruleActionParam.name()); + param.setValue(ruleActionParam.value()); + params.append(param); + } + action.setParams(params); + return action; +} + +ActionTypeId RuleAction::actionTypeId() const +{ + return m_actionTypeId; +} + +DeviceId RuleAction::deviceId() const +{ + return m_deviceId; +} + +RuleActionParamList RuleAction::ruleActionParams() const +{ + return m_ruleActionParams; +} + +void RuleAction::setRuleActionParams(const RuleActionParamList &ruleActionParams) +{ + m_ruleActionParams = ruleActionParams; +} + +RuleActionParam RuleAction::ruleActionParam(const QString &ruleActionParamName) const +{ + foreach (const RuleActionParam &ruleActionParam, m_ruleActionParams) { + if (ruleActionParam.name() == ruleActionParamName) { + return ruleActionParam; + } + } + return RuleActionParam(QString()); +} + +void RuleAction::operator=(const RuleAction &other) +{ + m_id = other.id(); + m_actionTypeId = other.actionTypeId(); + m_ruleActionParams = other.ruleActionParams(); +} diff --git a/libguh/types/ruleaction.h b/libguh/types/ruleaction.h new file mode 100644 index 00000000..d6a960ea --- /dev/null +++ b/libguh/types/ruleaction.h @@ -0,0 +1,36 @@ +#ifndef RULEACTION_H +#define RULEACTION_H + +#include "action.h" +#include "ruleactionparam.h" + +class RuleAction +{ +public: + explicit RuleAction(const ActionTypeId &actionTypeId = ActionTypeId(), const DeviceId &deviceId = DeviceId()); + RuleAction(const RuleAction &other); + + ActionId id() const; + bool isValid() const; + + bool isEventBased() const; + + Action toAction() const; + + ActionTypeId actionTypeId() const; + DeviceId deviceId() const; + + RuleActionParamList ruleActionParams() const; + void setRuleActionParams(const RuleActionParamList &ruleActionParams); + RuleActionParam ruleActionParam(const QString &ruleActionParamName) const; + + void operator=(const RuleAction &other); + +private: + ActionId m_id; + ActionTypeId m_actionTypeId; + DeviceId m_deviceId; + RuleActionParamList m_ruleActionParams; +}; + +#endif // RULEACTION_H diff --git a/libguh/types/ruleactionparam.cpp b/libguh/types/ruleactionparam.cpp index 53359cd3..c1806ff6 100644 --- a/libguh/types/ruleactionparam.cpp +++ b/libguh/types/ruleactionparam.cpp @@ -18,52 +18,145 @@ /*! \class RuleActionParam - \brief Holds the parameters for a rule action. + \brief Holds the parameters for a \l{RuleAction}. \ingroup types \inmodule libguh - A RuleActionParam allows in rules to take over an \l{Event} parameter into a rule - \l{Action}. + A RuleActionParam allows rules to take over an \l{Event} parameter into a rule + \l{RuleAction}. - \sa Rule, Action, Param, ParamType, ParamDescriptor + \sa Rule, RuleAction, */ #include "ruleactionparam.h" /*! Constructs a \l{RuleActionParam} with the given \a param. * \sa Param, */ -RuleActionParam::RuleActionParam(const Param ¶m) +RuleActionParam::RuleActionParam(const Param ¶m) : + m_name(param.name()), + m_value(param.value()) { - m_name = param.name(); - m_value = param.value(); } -/*! Constructs a \l{RuleActionParam} with the given \a name, \a value and \a eventId. +/*! Constructs a \l{RuleActionParam} with the given \a name, \a value and \a eventTypeId. * \sa Param, Event, */ -RuleActionParam::RuleActionParam(const QString &name, const QVariant &value, const EventId &eventId) : +RuleActionParam::RuleActionParam(const QString &name, const QVariant &value, const EventTypeId &eventTypeId) : m_name(name), m_value(value), - m_eventId(eventId) + m_eventTypeId(eventTypeId) { } -/*! Return the EventId of the \l{Event} with the \l{Param} which will be taken over in the \l{Rule}{rule} \l{Action}{action}. */ -EventId RuleActionParam::eventId() const +/*! Returns the name of this RuleActionParam. */ +QString RuleActionParam::name() const { - return m_eventId; + return m_name; } -/*! Sets the \a eventId of the \l{Event} with the \l{Param} which will be taken over in the \l{Rule}{rule} \l{Action}{action}. */ -void RuleActionParam::setEventId(const EventId &eventId) +/*! Sets the \a name of this RuleActionParam. */ +void RuleActionParam::setName(const QString &name) { - m_eventId = eventId; + m_name = name; } -/*! Writes the name and value of the given \a param to \a dbg. */ -QDebug operator<<(QDebug dbg, const RuleActionParam ¶m) +/*! Returns the value of this RuleActionParam. */ +QVariant RuleActionParam::value() const { - dbg.nospace() << "RuleActionParam(Name: " << param.name() << ", Value:" << param.value() << ", EventId:" << param.eventId().toString() << ")"; + return m_value; +} + +/*! Sets the \a value of this RuleActionParam. */ +void RuleActionParam::setValue(const QVariant &value) +{ + m_value = value; +} + +/*! Returns true if the name and the value of this RuleActionParam are set.*/ +bool RuleActionParam::isValid() const +{ + return !m_name.isEmpty() && m_value.isValid(); +} + +/*! Return the EventTypeId of the \l{Event} with the \l{Param} which will be taken over in the \l{RuleAction}. */ +EventTypeId RuleActionParam::eventTypeId() const +{ + return m_eventTypeId; +} + +/*! Sets the \a eventTypeId of the \l{Event} with the \l{Param} which will be taken over in the \l{RuleAction}. */ +void RuleActionParam::setEventTypeId(const EventTypeId &eventTypeId) +{ + m_eventTypeId = eventTypeId; +} + +/*! Writes the name, value and eventId of the given \a ruleActionParam to \a dbg. */ +QDebug operator<<(QDebug dbg, const RuleActionParam &ruleActionParam) +{ + dbg.nospace() << "RuleActionParam(Name: " << ruleActionParam.name() << ", Value:" << ruleActionParam.value() << ", EventTypeId:" << ruleActionParam.eventTypeId().toString() << ")"; + + return dbg.space(); +} + +// ActionTypeParamList + +/*! + \class RuleActionParamList + \brief Holds a list of \l{RuleActionParam}{RuleActionParams} + + \ingroup types + \inmodule libguh + + \sa RuleActionParam, RuleAction, +*/ + +/*! Returns true if this \l{RuleActionParamList} contains a RuleActionParam with the given \a paramName. */ +bool RuleActionParamList::hasParam(const QString &ruleActionParamName) const +{ + foreach (const RuleActionParam ¶m, *this) { + if (param.name() == ruleActionParamName) { + return true; + } + } + return false; +} + +/*! Returns the value of the \l{RuleActionParam} with the given \a ruleActionParamName. */ +QVariant RuleActionParamList::paramValue(const QString &ruleActionParamName) const +{ + foreach (const RuleActionParam ¶m, *this) { + if (param.name() == ruleActionParamName) { + return param.value(); + } + } + return QVariant(); +} + +/*! Sets the value of the \l{RuleActionParam} with the given \a ruleActionParamName to the given \a value. */ +void RuleActionParamList::setParamValue(const QString &ruleActionParamName, const QVariant &value) +{ + for (int i = 0; i < count(); i++) { + if (this->operator [](i).name() == ruleActionParamName) { + this->operator [](i).setValue(value); + return; + } + } +} + +/*! Appends the given \a ruleActionParam to a RuleActionParamList. */ +RuleActionParamList RuleActionParamList::operator<<(const RuleActionParam &ruleActionParam) +{ + this->append(ruleActionParam); + return *this; +} + +/*! Writes the ruleActionParam of the given \a ruleActionParams to \a dbg. */ +QDebug operator<<(QDebug dbg, const RuleActionParamList &ruleActionParams) +{ + dbg.nospace() << "RuleActionParamList (count:" << ruleActionParams.count() << ")" << endl; + for (int i = 0; i < ruleActionParams.count(); i++ ) { + dbg.nospace() << " " << i << ": " << ruleActionParams.at(i) << endl; + } return dbg.space(); } diff --git a/libguh/types/ruleactionparam.h b/libguh/types/ruleactionparam.h index 7795ae5a..730f6bb5 100644 --- a/libguh/types/ruleactionparam.h +++ b/libguh/types/ruleactionparam.h @@ -20,6 +20,8 @@ #define RULEACTIONPARAM_H #include +#include +#include #include "param.h" #include "typeutils.h" @@ -28,16 +30,38 @@ class RuleActionParam : public Param { public: RuleActionParam(const Param ¶m); - RuleActionParam(const QString &name = QString(), const QVariant &value = QVariant(), const EventId &eventId = EventId()); + RuleActionParam(const QString &name = QString(), const QVariant &value = QVariant(), const EventTypeId &eventTypeId = EventTypeId()); - EventId eventId() const; - void setEventId(const EventId &eventId); + QString name() const; + void setName(const QString &name); + + QVariant value() const; + void setValue(const QVariant &value); + + bool isValid() const; + + EventTypeId eventTypeId() const; + void setEventTypeId(const EventTypeId &eventTypeId); private: - EventId m_eventId; + QString m_name; + QVariant m_value; + EventTypeId m_eventTypeId; }; Q_DECLARE_METATYPE(RuleActionParam) -QDebug operator<<(QDebug dbg, const RuleActionParam ¶ms); +QDebug operator<<(QDebug dbg, const RuleActionParam &ruleActionParams); + + +class RuleActionParamList: public QList +{ +public: + bool hasParam(const QString &ruleActionParamName) const; + QVariant paramValue(const QString &ruleActionParamName) const; + void setParamValue(const QString &ruleActionParamName, const QVariant &value); + RuleActionParamList operator<<(const RuleActionParam &ruleActionParam); +}; +QDebug operator<<(QDebug dbg, const RuleActionParamList &ruleActionParams); + #endif // RULEACTIONPARAM_H diff --git a/server/guhcore.cpp b/server/guhcore.cpp index 3fd8ad1a..bd52fb76 100644 --- a/server/guhcore.cpp +++ b/server/guhcore.cpp @@ -286,7 +286,7 @@ Rule GuhCore::findRule(const RuleId &ruleId) /*! Calls the metheod RuleEngine::addRule(\a id, \a name, \a eventDescriptorList, \a stateEvaluator \a actionList, \a exitActionList, \a enabled). * \sa RuleEngine, */ -RuleEngine::RuleError GuhCore::addRule(const RuleId &id, const QString &name, const QList &eventDescriptorList, const StateEvaluator &stateEvaluator, const QList &actionList, const QList &exitActionList, bool enabled) +RuleEngine::RuleError GuhCore::addRule(const RuleId &id, const QString &name, const QList &eventDescriptorList, const StateEvaluator &stateEvaluator, const QList &actionList, const QList &exitActionList, bool enabled) { return m_ruleEngine->addRule(id, name, eventDescriptorList, stateEvaluator, actionList, exitActionList, enabled); } @@ -365,18 +365,28 @@ GuhCore::GuhCore(QObject *parent) : } /*! Connected to the DeviceManager's emitEvent signal. Events received in - here will be evaluated by the \l{RuleEngine} and the according \l{Action}{Actions} are executed.*/ + here will be evaluated by the \l{RuleEngine} and the according \l{RuleAction}{RuleActions} are executed.*/ void GuhCore::gotEvent(const Event &event) { m_logger->logEvent(event); emit eventTriggered(event); - QList actions; + QList actions; + QList eventBasedActions; foreach (const Rule &rule, m_ruleEngine->evaluateEvent(event)) { + // Event based if (rule.eventDescriptors().count() > 0) { m_logger->logRuleTriggered(rule); - actions.append(rule.actions()); + // check if we have an event based action or a normal action + foreach (const RuleAction &action, rule.actions()) { + if (action.isEventBased()) { + eventBasedActions.append(action); + } else { + actions.append(rule.actions()); + } + } } else { + // State based rule m_logger->logRuleActiveChanged(rule); if (rule.active()) { actions.append(rule.actions()); @@ -386,9 +396,25 @@ void GuhCore::gotEvent(const Event &event) } } + // Convert event based RuleActions to normal action, depending on the event value + foreach (const RuleAction &ruleAction, eventBasedActions) { + foreach (RuleActionParam ruleActionParam, ruleAction.ruleActionParams()) { + // if this event param should be taken over in this action + if (event.eventTypeId() == ruleActionParam.eventTypeId()) { + QVariant eventValue = event.param(ruleActionParam.name()).value(); + + // TODO: limits / scale calculation -> actionValue = eventValue * x + + ruleActionParam.setValue(eventValue); + } + } + actions.append(ruleAction); + } + // Now execute all the associated actions - foreach (const Action &action, actions) { - qDebug() << "executing action" << action.actionTypeId(); + foreach (const RuleAction &ruleAction, actions) { + Action action = ruleAction.toAction(); + qDebug() << "executing action" << ruleAction.actionTypeId(); DeviceManager::DeviceError status = m_deviceManager->executeAction(action); switch(status) { case DeviceManager::DeviceErrorNoError: diff --git a/server/guhcore.h b/server/guhcore.h index 8aeac521..68f8d801 100644 --- a/server/guhcore.h +++ b/server/guhcore.h @@ -75,7 +75,7 @@ public: QList rules() const; QList ruleIds() const; Rule findRule(const RuleId &ruleId); - RuleEngine::RuleError addRule(const RuleId &id, const QString &name, const QList &eventDescriptorList, const StateEvaluator &stateEvaluator, const QList &actionList, const QList &exitActionList, bool enabled = true); + RuleEngine::RuleError addRule(const RuleId &id, const QString &name, const QList &eventDescriptorList, const StateEvaluator &stateEvaluator, const QList &actionList, const QList &exitActionList, bool enabled = true); RuleEngine::RuleError removeRule(const RuleId &id); QList findRules(const DeviceId &deviceId); RuleEngine::RuleError enableRule(const RuleId &ruleId); diff --git a/server/jsonrpc/jsontypes.cpp b/server/jsonrpc/jsontypes.cpp index f4ee7dba..b285b4e4 100644 --- a/server/jsonrpc/jsontypes.cpp +++ b/server/jsonrpc/jsontypes.cpp @@ -46,6 +46,8 @@ QVariantList JsonTypes::s_loggingEventType; QVariantMap JsonTypes::s_paramType; QVariantMap JsonTypes::s_param; +QVariantMap JsonTypes::s_ruleAction; +QVariantMap JsonTypes::s_ruleActionParam; QVariantMap JsonTypes::s_paramDescriptor; QVariantMap JsonTypes::s_stateType; QVariantMap JsonTypes::s_state; @@ -94,6 +96,16 @@ void JsonTypes::init() s_param.insert("name", basicTypeToString(String)); s_param.insert("value", basicTypeRef()); + // RuleAction + s_ruleAction.insert("actionTypeId", basicTypeToString(Uuid)); + s_ruleAction.insert("deviceId", basicTypeToString(Uuid)); + s_ruleAction.insert("o:ruleActionParams", QVariantList() << ruleActionParamRef()); + + // RuleActionParam + s_ruleActionParam.insert("name", basicTypeToString(String)); + s_ruleActionParam.insert("o:value", basicTypeRef()); + s_ruleActionParam.insert("o:eventId", basicTypeToString(Uuid)); + // ParamDescriptor s_paramDescriptor.insert("name", basicTypeToString(String)); s_paramDescriptor.insert("value", basicTypeRef()); @@ -184,8 +196,8 @@ void JsonTypes::init() s_rule.insert("name", basicTypeToString(String)); s_rule.insert("enabled", basicTypeToString(Bool)); s_rule.insert("eventDescriptors", QVariantList() << eventDescriptorRef()); - s_rule.insert("actions", QVariantList() << actionRef()); - s_rule.insert("exitActions", QVariantList() << actionRef()); + s_rule.insert("actions", QVariantList() << ruleActionRef()); + s_rule.insert("exitActions", QVariantList() << ruleActionRef()); s_rule.insert("stateEvaluator", stateEvaluatorRef()); // LogEntry @@ -249,6 +261,8 @@ QVariantMap JsonTypes::allTypes() allTypes.insert("DeviceClass", deviceClassDescription()); allTypes.insert("Plugin", pluginDescription()); allTypes.insert("Param", paramDescription()); + allTypes.insert("RuleAction", ruleActionDescription()); + allTypes.insert("RuleActionParam", ruleActionParamDescription()); allTypes.insert("ParamDescriptor", paramDescriptorDescription()); allTypes.insert("State", stateDescription()); allTypes.insert("Device", deviceDescription()); @@ -324,6 +338,28 @@ QVariantMap JsonTypes::packAction(const Action &action) return variant; } +QVariantMap JsonTypes::packRuleAction(const RuleAction &ruleAction) +{ + QVariantMap variant; + variant.insert("actionTypeId", ruleAction.actionTypeId()); + variant.insert("deviceId", ruleAction.deviceId()); + QVariantList params; + foreach (const RuleActionParam &ruleActionParam, ruleAction.ruleActionParams()) { + params.append(packRuleActionParam(ruleActionParam)); + } + variant.insert("ruleActionParams", params); + return variant; +} + +QVariantMap JsonTypes::packRuleActionParam(const RuleActionParam &ruleActionParam) +{ + QVariantMap variantMap; + variantMap.insert("name", ruleActionParam.name()); + variantMap.insert("value", ruleActionParam.value()); + variantMap.insert("eventTypeId", ruleActionParam.eventTypeId()); + return variantMap; +} + QVariantMap JsonTypes::packStateType(const StateType &stateType) { QVariantMap variantMap; @@ -493,16 +529,16 @@ QVariantMap JsonTypes::packRule(const Rule &rule) ruleMap.insert("eventDescriptors", eventDescriptorList); QVariantList actionList; - foreach (const Action &action, rule.actions()) { - actionList.append(JsonTypes::packAction(action)); + foreach (const RuleAction &action, rule.actions()) { + actionList.append(JsonTypes::packRuleAction(action)); } + ruleMap.insert("actions", actionList); + QVariantList exitActionList; - foreach (const Action &action, rule.exitActions()) { - exitActionList.append(JsonTypes::packAction(action)); + foreach (const RuleAction &action, rule.exitActions()) { + exitActionList.append(JsonTypes::packRuleAction(action)); } ruleMap.insert("exitActions", exitActionList); - - ruleMap.insert("actions", actionList); ruleMap.insert("stateEvaluator", JsonTypes::packStateEvaluator(rule.stateEvaluator())); return ruleMap; } @@ -584,12 +620,31 @@ ParamList JsonTypes::unpackParams(const QVariantList ¶mList) { ParamList params; foreach (const QVariant ¶mVariant, paramList) { - // qDebug() << "unpacking param" << paramVariant; params.append(unpackParam(paramVariant.toMap())); } return params; } +RuleActionParam JsonTypes::unpackRuleActionParam(const QVariantMap &ruleActionParamMap) +{ + if (ruleActionParamMap.keys().count() == 0) { + return RuleActionParam(); + } + QString name = ruleActionParamMap.value("name").toString(); + QVariant value = ruleActionParamMap.value("value"); + EventTypeId eventTypeId(ruleActionParamMap.value("eventTypeId").toString()); + return RuleActionParam(name, value, eventTypeId); +} + +RuleActionParamList JsonTypes::unpackRuleActionParams(const QVariantList &ruleActionParamList) +{ + RuleActionParamList ruleActionParams; + foreach (const QVariant ¶mVariant, ruleActionParamList) { + ruleActionParams.append(unpackRuleActionParam(paramVariant.toMap())); + } + return ruleActionParams; +} + ParamDescriptor JsonTypes::unpackParamDescriptor(const QVariantMap ¶mMap) { ParamDescriptor param(paramMap.value("name").toString(), paramMap.value("value")); diff --git a/server/jsonrpc/jsontypes.h b/server/jsonrpc/jsontypes.h index 77e8b14d..9922a93c 100644 --- a/server/jsonrpc/jsontypes.h +++ b/server/jsonrpc/jsontypes.h @@ -30,6 +30,7 @@ #include "types/actiontype.h" #include "types/paramtype.h" #include "types/paramdescriptor.h" +#include "types/ruleactionparam.h" #include "logging/logging.h" #include "logging/logentry.h" @@ -107,6 +108,8 @@ public: DECLARE_OBJECT(paramType, "ParamType") DECLARE_OBJECT(param, "Param") DECLARE_OBJECT(paramDescriptor, "ParamDescriptor") + DECLARE_OBJECT(ruleAction, "RuleAction") + DECLARE_OBJECT(ruleActionParam, "RuleActionParam") DECLARE_OBJECT(stateType, "StateType") DECLARE_OBJECT(stateDescriptor, "StateDescriptor") DECLARE_OBJECT(state, "State") @@ -129,6 +132,8 @@ public: static QVariantMap packEventDescriptor(const EventDescriptor &event); static QVariantMap packActionType(const ActionType &actionType); static QVariantMap packAction(const Action &action); + static QVariantMap packRuleAction(const RuleAction &ruleAction); + static QVariantMap packRuleActionParam(const RuleActionParam &ruleActionParam); static QVariantMap packStateType(const StateType &stateType); static QVariantMap packStateDescriptor(const StateDescriptor &stateDescriptor); static QVariantMap packStateEvaluator(const StateEvaluator &stateEvaluator); @@ -146,6 +151,8 @@ public: static Param unpackParam(const QVariantMap ¶mMap); static ParamList unpackParams(const QVariantList ¶mList); + static RuleActionParam unpackRuleActionParam(const QVariantMap &ruleActionParamMap); + static RuleActionParamList unpackRuleActionParams(const QVariantList &ruleActionParamList); static ParamDescriptor unpackParamDescriptor(const QVariantMap ¶mDescriptorMap); static QList unpackParamDescriptors(const QVariantList ¶mDescriptorList); static EventDescriptor unpackEventDescriptor(const QVariantMap &eventDescriptorMap); diff --git a/server/jsonrpc/ruleshandler.cpp b/server/jsonrpc/ruleshandler.cpp index f4381510..18a56e1a 100644 --- a/server/jsonrpc/ruleshandler.cpp +++ b/server/jsonrpc/ruleshandler.cpp @@ -154,32 +154,62 @@ JsonReply* RulesHandler::AddRule(const QVariantMap ¶ms) qDebug() << "unpacking:" << params.value("stateEvaluator").toMap(); StateEvaluator stateEvaluator = JsonTypes::unpackStateEvaluator(params.value("stateEvaluator").toMap()); - QList actions; + QList actions; QVariantList actionList = params.value("actions").toList(); foreach (const QVariant &actionVariant, actionList) { QVariantMap actionMap = actionVariant.toMap(); - Action action(ActionTypeId(actionMap.value("actionTypeId").toString()), DeviceId(actionMap.value("deviceId").toString())); - qDebug() << "params from json" << actionMap.value("params"); - action.setParams(JsonTypes::unpackParams(actionMap.value("params").toList())); - qDebug() << "params in action" << action.params(); + RuleAction action(ActionTypeId(actionMap.value("actionTypeId").toString()), DeviceId(actionMap.value("deviceId").toString())); + qDebug() << "params from json" << actionMap.value("ruleActionParams"); + action.setRuleActionParams(JsonTypes::unpackRuleActionParams(actionMap.value("ruleActionParams").toList())); + qDebug() << "params in action" << action.ruleActionParams(); actions.append(action); } + // check possible eventTypeIds in params + foreach (const RuleAction &ruleAction, actions) { + if (ruleAction.isEventBased()) { + foreach (const RuleActionParam &ruleActionParam, ruleAction.ruleActionParams()) { + if (ruleActionParam.eventTypeId() != EventTypeId()) { + // We have an eventTypeId + if (eventDescriptorList.isEmpty()) { + QVariantMap returns; + qWarning() << "RuleAction" << ruleAction.actionTypeId() << "contains an eventTypeId, but there areno eventDescriptors."; + returns.insert("ruleErorr", JsonTypes::ruleErrorToString(RuleEngine::RuleErrorInvalidRuleActionPatameter)); + return createReply(returns); + } + // now check if this eventType is in the eventDescriptorList of this rule + foreach (const EventDescriptor eventDescriptor, eventDescriptorList) { + if (eventDescriptor.eventTypeId() == ruleActionParam.eventTypeId()) { + continue; + } else { + // the given eventTypeId is not in the eventDescriptorList + QVariantMap returns; + qWarning() << "eventTypeId from RuleAction" << ruleAction.actionTypeId() << "missing in eventDescriptors."; + returns.insert("ruleErorr", JsonTypes::ruleErrorToString(RuleEngine::RuleErrorInvalidRuleActionPatameter)); + return createReply(returns); + } + } + } + } + } + } + + QVariantMap returns; if (actions.count() == 0) { returns.insert("ruleErorr", JsonTypes::ruleErrorToString(RuleEngine::RuleErrorMissingParameter)); return createReply(returns); } - QList exitActions; + QList exitActions; if (params.contains("exitActions")) { QVariantList exitActionList = params.value("exitActions").toList(); foreach (const QVariant &actionVariant, exitActionList) { QVariantMap actionMap = actionVariant.toMap(); - Action action(ActionTypeId(actionMap.value("actionTypeId").toString()), DeviceId(actionMap.value("deviceId").toString())); - qDebug() << "params from json" << actionMap.value("params"); - action.setParams(JsonTypes::unpackParams(actionMap.value("params").toList())); - qDebug() << "params in action" << action.params(); + RuleAction action(ActionTypeId(actionMap.value("actionTypeId").toString()), DeviceId(actionMap.value("deviceId").toString())); + qDebug() << "params from json" << actionMap.value("ruleActionParams"); + action.setRuleActionParams(JsonTypes::unpackRuleActionParams(actionMap.value("ruleActionParams").toList())); + qDebug() << "params in action" << action.ruleActionParams(); exitActions.append(action); } } diff --git a/server/jsonrpc/ruleshandler.h b/server/jsonrpc/ruleshandler.h index c0d1baca..81002723 100644 --- a/server/jsonrpc/ruleshandler.h +++ b/server/jsonrpc/ruleshandler.h @@ -38,6 +38,7 @@ public: Q_INVOKABLE JsonReply* EnableRule(const QVariantMap ¶ms); Q_INVOKABLE JsonReply* DisableRule(const QVariantMap ¶ms); + }; #endif // RULESHANDLER_H diff --git a/server/rule.cpp b/server/rule.cpp index cbbbdbe7..e63bb009 100644 --- a/server/rule.cpp +++ b/server/rule.cpp @@ -24,9 +24,9 @@ \inmodule server A Rule is always triggered by an \l{EventDescriptor}, has \l{State}{States} - to be compared and \l{Action}{Actions} to be executed. + to be compared and \l{RuleAction}{RuleActions} to be executed. - \sa EventDescriptor, State, Action + \sa EventDescriptor, State, RuleAction */ #include "rule.h" @@ -35,12 +35,12 @@ /*! Constructs an empty, invalid rule. */ Rule::Rule(): - Rule(RuleId(), QString(), QList(), StateEvaluator(), QList(), QList()) + Rule(RuleId(), QString(), QList(), StateEvaluator(), QList(), QList()) { } /*! Constructs a Rule with the given \a id, \a name, \a eventDescriptorList, \a stateEvaluator and \a actions.*/ -Rule::Rule(const RuleId &id, const QString &name, const QList &eventDescriptorList, const StateEvaluator &stateEvaluator, const QList &actions) : +Rule::Rule(const RuleId &id, const QString &name, const QList &eventDescriptorList, const StateEvaluator &stateEvaluator, const QList &actions) : m_id(id), m_name(name), m_eventDescriptors(eventDescriptorList), @@ -53,7 +53,7 @@ Rule::Rule(const RuleId &id, const QString &name, const QList & } /*! Constructs a Rule with the given \a id, \a name, \a eventDescriptorList, \a stateEvaluator, \a actions and \a exitActions.*/ -Rule::Rule(const RuleId &id, const QString &name, const QList &eventDescriptorList, const StateEvaluator &stateEvaluator, const QList &actions, const QList &exitActions): +Rule::Rule(const RuleId &id, const QString &name, const QList &eventDescriptorList, const StateEvaluator &stateEvaluator, const QList &actions, const QList &exitActions): m_id(id), m_name(name), m_eventDescriptors(eventDescriptorList), @@ -68,7 +68,7 @@ Rule::Rule(const RuleId &id, const QString &name, const QList & /*! Constructs a Rule with the given \a id, \a name, \a stateEvaluator, \a actions and \a exitActions. This type of rule * works only state based and executes the \a actions once the rule enters the active state and executes the \a exitActions * once the rule exits the active state.*/ -Rule::Rule(const RuleId &id, const QString &name, const StateEvaluator &stateEvaluator, const QList &actions, const QList &exitActions) : +Rule::Rule(const RuleId &id, const QString &name, const StateEvaluator &stateEvaluator, const QList &actions, const QList &exitActions) : m_id(id), m_name(name), m_stateEvaluator(stateEvaluator), @@ -97,14 +97,14 @@ StateEvaluator Rule::stateEvaluator() const return m_stateEvaluator; } -/*! Returns the \l{Action}{Actions} to be executed when this Rule is matched and states match. */ -QList Rule::actions() const +/*! Returns the \l{RuleAction}{RuleActions} to be executed when this Rule is matched and states match. */ +QList Rule::actions() const { return m_actions; } -/*! Returns the \l{Action}{Actions} to be executed when this Rule leaves the active state. */ -QList Rule::exitActions() const +/*! Returns the \l{RuleAction}{RuleActions} to be executed when this Rule leaves the active state. */ +QList Rule::exitActions() const { return m_exitActions; } diff --git a/server/rule.h b/server/rule.h index 0867f77e..06e027dc 100644 --- a/server/rule.h +++ b/server/rule.h @@ -20,7 +20,7 @@ #define RULE_H #include "types/state.h" -#include "types/action.h" +#include "types/ruleaction.h" #include "types/eventdescriptor.h" #include "stateevaluator.h" @@ -30,15 +30,15 @@ class Rule { public: Rule(); - Rule(const RuleId &id, const QString &name, const QList &eventDescriptorList, const StateEvaluator &stateEvaluator, const QList &actions); - Rule(const RuleId &id, const QString &name, const QList &eventDescriptorList, const StateEvaluator &stateEvaluator, const QList &actions, const QList &exitActions); - Rule(const RuleId &id, const QString &name, const StateEvaluator &stateEvaluator, const QList &actions, const QList &exitActions); + Rule(const RuleId &id, const QString &name, const QList &eventDescriptorList, const StateEvaluator &stateEvaluator, const QList &actions); + Rule(const RuleId &id, const QString &name, const QList &eventDescriptorList, const StateEvaluator &stateEvaluator, const QList &actions, const QList &exitActions); + Rule(const RuleId &id, const QString &name, const StateEvaluator &stateEvaluator, const QList &actions, const QList &exitActions); RuleId id() const; QList eventDescriptors() const; StateEvaluator stateEvaluator() const; - QList actions() const; - QList exitActions() const; + QList actions() const; + QList exitActions() const; QString name() const; bool enabled() const; @@ -56,8 +56,8 @@ private: QString m_name; QList m_eventDescriptors; StateEvaluator m_stateEvaluator; - QList m_actions; - QList m_exitActions; + QList m_actions; + QList m_exitActions; bool m_enabled; bool m_active; diff --git a/server/ruleengine.cpp b/server/ruleengine.cpp index d8f09e25..1b6113fd 100644 --- a/server/ruleengine.cpp +++ b/server/ruleengine.cpp @@ -27,7 +27,7 @@ You can add, remove and update rules and query the engine for actions to be executed for a given \l{Event} described by an \l{EventDescriptor}. - \sa Event, EventDescriptor, Rule, Action + \sa Event, EventDescriptor, Rule, RuleAction */ /*! \fn void RuleEngine::ruleAdded(const RuleId &ruleId) @@ -130,42 +130,42 @@ RuleEngine::RuleEngine(QObject *parent) : StateEvaluator stateEvaluator = StateEvaluator::loadFromSettings(settings, "stateEvaluator"); - settings.beginGroup("actions"); - QList actions; + settings.beginGroup("ruleActions"); + QList actions; foreach (const QString &actionIdString, settings.childGroups()) { settings.beginGroup(actionIdString); - Action action = Action(ActionTypeId(settings.value("actionTypeId").toString()), DeviceId(settings.value("deviceId").toString())); - ParamList params; + RuleAction action = RuleAction(ActionTypeId(settings.value("actionTypeId").toString()), DeviceId(settings.value("deviceId").toString())); + RuleActionParamList params; foreach (QString paramNameString, settings.childGroups()) { - if (paramNameString.startsWith("Param-")) { + if (paramNameString.startsWith("RuleActionParam-")) { settings.beginGroup(paramNameString); - Param param(paramNameString.remove(QRegExp("^Param-")), settings.value("value")); + RuleActionParam param(paramNameString.remove(QRegExp("^RuleActionParam-")), settings.value("value")); params.append(param); settings.endGroup(); } } - action.setParams(params); + action.setRuleActionParams(params); settings.endGroup(); actions.append(action); } settings.endGroup(); - settings.beginGroup("exitActions"); - QList exitActions; + settings.beginGroup("ruleExitActions"); + QList exitActions; foreach (const QString &actionIdString, settings.childGroups()) { settings.beginGroup(actionIdString); - Action action = Action(ActionTypeId(settings.value("actionTypeId").toString()), DeviceId(settings.value("deviceId").toString())); - ParamList params; + RuleAction action = RuleAction(ActionTypeId(settings.value("actionTypeId").toString()), DeviceId(settings.value("deviceId").toString())); + RuleActionParamList params; foreach (QString paramNameString, settings.childGroups()) { - if (paramNameString.startsWith("Param-")) { + if (paramNameString.startsWith("RuleActionParam-")) { settings.beginGroup(paramNameString); - Param param(paramNameString.remove(QRegExp("^Param-")), settings.value("value")); + RuleActionParam param(paramNameString.remove(QRegExp("^RuleActionParam-")), settings.value("value")); params.append(param); settings.endGroup(); } } - action.setParams(params); + action.setRuleActionParams(params); settings.endGroup(); exitActions.append(action); @@ -235,13 +235,13 @@ QList RuleEngine::evaluateEvent(const Event &event) /*! Add a new \l{Rule} with the given \a ruleId , \a name, \a eventDescriptorList, \a actions and \a enabled value to the engine. For convenience, this creates a Rule without any \l{State} comparison. */ -RuleEngine::RuleError RuleEngine::addRule(const RuleId &ruleId, const QString &name, const QList &eventDescriptorList, const QList &actions, bool enabled) +RuleEngine::RuleError RuleEngine::addRule(const RuleId &ruleId, const QString &name, const QList &eventDescriptorList, const QList &actions, bool enabled) { - return addRule(ruleId, name, eventDescriptorList, StateEvaluator(), actions, QList(), enabled); + return addRule(ruleId, name, eventDescriptorList, StateEvaluator(), actions, QList(), enabled); } /*! Add a new \l{Rule} with the given \a ruleId, \a name, \a eventDescriptorList, \a stateEvaluator, the list of \a actions the list of \a exitActions and the \a enabled value to the engine.*/ -RuleEngine::RuleError RuleEngine::addRule(const RuleId &ruleId, const QString &name, const QList &eventDescriptorList, const StateEvaluator &stateEvaluator, const QList &actions, const QList &exitActions, bool enabled) +RuleEngine::RuleError RuleEngine::addRule(const RuleId &ruleId, const QString &name, const QList &eventDescriptorList, const StateEvaluator &stateEvaluator, const QList &actions, const QList &exitActions, bool enabled) { if (ruleId.isNull()) { return RuleErrorInvalidRuleId; @@ -273,7 +273,7 @@ RuleEngine::RuleError RuleEngine::addRule(const RuleId &ruleId, const QString &n } } - foreach (const Action &action, actions) { + foreach (const RuleAction &action, actions) { Device *device = GuhCore::instance()->findConfiguredDevice(action.deviceId()); if (!device) { qWarning() << "Cannot create rule. No configured device for actionTypeId" << action.actionTypeId(); @@ -293,10 +293,10 @@ RuleEngine::RuleError RuleEngine::addRule(const RuleId &ruleId, const QString &n } } if (actions.count() > 0) { - qDebug() << "***** actions" << actions.last().actionTypeId() << actions.last().params(); + qDebug() << "***** actions" << actions.last().actionTypeId() << actions.last().ruleActionParams(); } - foreach (const Action &action, exitActions) { + foreach (const RuleAction &action, exitActions) { Device *device = GuhCore::instance()->findConfiguredDevice(action.deviceId()); if (!device) { qWarning() << "Cannot create rule. No configured device for actionTypeId" << action.actionTypeId(); @@ -316,7 +316,7 @@ RuleEngine::RuleError RuleEngine::addRule(const RuleId &ruleId, const QString &n } } if (exitActions.count() > 0) { - qDebug() << "***** exitActions" << actions.last().actionTypeId() << actions.last().params(); + qDebug() << "***** exitActions" << actions.last().actionTypeId() << actions.last().ruleActionParams(); } Rule rule = Rule(ruleId, name, eventDescriptorList, stateEvaluator, actions, exitActions); @@ -347,13 +347,13 @@ RuleEngine::RuleError RuleEngine::addRule(const RuleId &ruleId, const QString &n stateEvaluator.dumpToSettings(settings, "stateEvaluator"); - settings.beginGroup("actions"); - foreach (const Action &action, rule.actions()) { + settings.beginGroup("ruleActions"); + foreach (const RuleAction &action, rule.actions()) { settings.beginGroup(action.actionTypeId().toString()); settings.setValue("deviceId", action.deviceId()); settings.setValue("actionTypeId", action.actionTypeId()); - foreach (const Param ¶m, action.params()) { - settings.beginGroup("Param-" + param.name()); + foreach (const RuleActionParam ¶m, action.ruleActionParams()) { + settings.beginGroup("RuleActionParam-" + param.name()); settings.setValue("value", param.value()); settings.endGroup(); } @@ -363,12 +363,12 @@ RuleEngine::RuleError RuleEngine::addRule(const RuleId &ruleId, const QString &n settings.endGroup(); settings.beginGroup("exitActions"); - foreach (const Action &action, rule.exitActions()) { + foreach (const RuleAction &action, rule.exitActions()) { settings.beginGroup(action.actionTypeId().toString()); settings.setValue("deviceId", action.deviceId()); settings.setValue("actionTypeId", action.actionTypeId()); - foreach (const Param ¶m, action.params()) { - settings.beginGroup("Param-" + param.name()); + foreach (const RuleActionParam ¶m, action.ruleActionParams()) { + settings.beginGroup("RuleActionParam-" + param.name()); settings.setValue("value", param.value()); settings.endGroup(); } @@ -446,7 +446,7 @@ QList RuleEngine::findRules(const DeviceId &deviceId) offending = true; } if (!offending) { - foreach (const Action &action, rule.actions()) { + foreach (const RuleAction &action, rule.actions()) { if (action.deviceId() == deviceId) { offending = true; break; @@ -480,7 +480,7 @@ void RuleEngine::removeDeviceFromRule(const RuleId &id, const DeviceId &deviceId StateEvaluator stateEvalatuator = rule.stateEvaluator(); stateEvalatuator.removeDevice(deviceId); - QList actions = rule.actions(); + QList actions = rule.actions(); for (int i = 0; i < actions.count(); i++) { if (actions.at(i).deviceId() == deviceId) { removeIndexes.append(i); diff --git a/server/ruleengine.h b/server/ruleengine.h index 9905dbd8..942da597 100644 --- a/server/ruleengine.h +++ b/server/ruleengine.h @@ -42,7 +42,8 @@ public: RuleErrorActionTypeNotFound, RuleErrorInvalidParameter, RuleErrorInvalidRuleFormat, - RuleErrorMissingParameter + RuleErrorMissingParameter, + RuleErrorInvalidRuleActionPatameter }; enum RemovePolicy { @@ -54,8 +55,8 @@ public: QList evaluateEvent(const Event &event); - RuleError addRule(const RuleId &ruleId, const QString &name, const QList &eventDescriptorList, const QList &actions, bool enabled = true); - RuleError addRule(const RuleId &ruleId, const QString &name, const QList &eventDescriptorList, const StateEvaluator &stateEvaluator, const QList &actions, const QList &exitActions, bool enabled = true); + RuleError addRule(const RuleId &ruleId, const QString &name, const QList &eventDescriptorList, const QList &actions, bool enabled = true); + RuleError addRule(const RuleId &ruleId, const QString &name, const QList &eventDescriptorList, const StateEvaluator &stateEvaluator, const QList &actions, const QList &exitActions, bool enabled = true); QList rules() const; QList ruleIds() const;