add Rules.EditRule method and Rules.CRuleConfigurationChanged notification

This commit is contained in:
Simon Stürz 2015-06-29 12:58:35 +02:00 committed by Michael Zanetti
parent f125511994
commit 85ba7af29c
7 changed files with 369 additions and 189 deletions

View File

@ -2,7 +2,7 @@
GUH_VERSION_STRING=$$system('dpkg-parsechangelog | sed -n -e "s/^Version: //p"') GUH_VERSION_STRING=$$system('dpkg-parsechangelog | sed -n -e "s/^Version: //p"')
# define JSON protocol version # define JSON protocol version
JSON_PROTOCOL_VERSION=26 JSON_PROTOCOL_VERSION=27
DEFINES += GUH_VERSION_STRING=\\\"$${GUH_VERSION_STRING}\\\" JSON_PROTOCOL_VERSION=\\\"$${JSON_PROTOCOL_VERSION}\\\" DEFINES += GUH_VERSION_STRING=\\\"$${GUH_VERSION_STRING}\\\" JSON_PROTOCOL_VERSION=\\\"$${JSON_PROTOCOL_VERSION}\\\"

View File

@ -339,6 +339,11 @@ RuleEngine::RuleError GuhCore::addRule(const RuleId &id, const QString &name, co
return m_ruleEngine->addRule(id, name, eventDescriptorList, stateEvaluator, actionList, exitActionList, enabled); return m_ruleEngine->addRule(id, name, eventDescriptorList, stateEvaluator, actionList, exitActionList, enabled);
} }
RuleEngine::RuleError GuhCore::editRule(const RuleId &id, const QString &name, const QList<EventDescriptor> &eventDescriptorList, const StateEvaluator &stateEvaluator, const QList<RuleAction> &actionList, const QList<RuleAction> &exitActionList, bool enabled)
{
return m_ruleEngine->editRule(id, name, eventDescriptorList, stateEvaluator, actionList, exitActionList, enabled);
}
/*! Calls the metheod RuleEngine::removeRule(\a id). /*! Calls the metheod RuleEngine::removeRule(\a id).
* \sa RuleEngine, */ * \sa RuleEngine, */
RuleEngine::RuleError GuhCore::removeRule(const RuleId &id) RuleEngine::RuleError GuhCore::removeRule(const RuleId &id)
@ -406,6 +411,7 @@ GuhCore::GuhCore(QObject *parent) :
connect(m_ruleEngine, &RuleEngine::ruleAdded, this, &GuhCore::ruleAdded); connect(m_ruleEngine, &RuleEngine::ruleAdded, this, &GuhCore::ruleAdded);
connect(m_ruleEngine, &RuleEngine::ruleRemoved, this, &GuhCore::ruleRemoved); connect(m_ruleEngine, &RuleEngine::ruleRemoved, this, &GuhCore::ruleRemoved);
connect(m_ruleEngine, &RuleEngine::ruleConfigurationChanged, this, &GuhCore::ruleConfigurationChanged);
m_logger->logSystemEvent(true); m_logger->logSystemEvent(true);
} }

View File

@ -82,6 +82,7 @@ public:
QList<RuleId> ruleIds() const; QList<RuleId> ruleIds() const;
Rule findRule(const RuleId &ruleId); Rule findRule(const RuleId &ruleId);
RuleEngine::RuleError addRule(const RuleId &id, const QString &name, const QList<EventDescriptor> &eventDescriptorList, const StateEvaluator &stateEvaluator, const QList<RuleAction> &actionList, const QList<RuleAction> &exitActionList, bool enabled = true); RuleEngine::RuleError addRule(const RuleId &id, const QString &name, const QList<EventDescriptor> &eventDescriptorList, const StateEvaluator &stateEvaluator, const QList<RuleAction> &actionList, const QList<RuleAction> &exitActionList, bool enabled = true);
RuleEngine::RuleError editRule(const RuleId &id, const QString &name, const QList<EventDescriptor> &eventDescriptorList, const StateEvaluator &stateEvaluator, const QList<RuleAction> &actionList, const QList<RuleAction> &exitActionList, bool enabled = true);
RuleEngine::RuleError removeRule(const RuleId &id); RuleEngine::RuleError removeRule(const RuleId &id);
QList<RuleId> findRules(const DeviceId &deviceId); QList<RuleId> findRules(const DeviceId &deviceId);
RuleEngine::RuleError enableRule(const RuleId &ruleId); RuleEngine::RuleError enableRule(const RuleId &ruleId);
@ -105,6 +106,7 @@ signals:
void ruleRemoved(const RuleId &ruleId); void ruleRemoved(const RuleId &ruleId);
void ruleAdded(const Rule &rule); void ruleAdded(const Rule &rule);
void ruleActiveChanged(const Rule &rule); void ruleActiveChanged(const Rule &rule);
void ruleConfigurationChanged(const Rule &rule);
private: private:

View File

@ -66,6 +66,25 @@ RulesHandler::RulesHandler(QObject *parent) :
returns.insert("o:ruleId", JsonTypes::basicTypeToString(JsonTypes::Uuid)); returns.insert("o:ruleId", JsonTypes::basicTypeToString(JsonTypes::Uuid));
setReturns("AddRule", returns); setReturns("AddRule", returns);
params.clear(); returns.clear(); actions.clear();
setDescription("EditRule", "Edit the parameters of a rule. The configuration of the rule with the given ruleId "
"will be replaced with the new given configuration. In ordert to enable or disable a Rule, please use the "
"methods \"Rules.EnableRule\" and \"Rules.DisableRule\". If successfull, the notification \"Rule.RuleConfigurationChanged\" "
"will be emitted.");
params.insert("ruleId", JsonTypes::basicTypeToString(JsonTypes::Uuid));
params.insert("name", JsonTypes::basicTypeToString(JsonTypes::String));
params.insert("o:eventDescriptor", JsonTypes::eventDescriptorRef());
params.insert("o:eventDescriptorList", QVariantList() << JsonTypes::eventDescriptorRef());
params.insert("o:stateEvaluator", JsonTypes::stateEvaluatorRef());
params.insert("o:exitActions", QVariantList() << JsonTypes::ruleActionRef());
params.insert("o:enabled", JsonTypes::basicTypeToString(JsonTypes::Bool));
actions.append(JsonTypes::ruleActionRef());
params.insert("actions", actions);
setParams("EditRule", params);
returns.insert("ruleError", JsonTypes::ruleErrorRef());
returns.insert("o:rule", JsonTypes::ruleRef());
setReturns("EditRule", returns);
params.clear(); returns.clear(); params.clear(); returns.clear();
setDescription("RemoveRule", "Remove a rule"); setDescription("RemoveRule", "Remove a rule");
params.insert("ruleId", JsonTypes::basicTypeToString(JsonTypes::Uuid)); params.insert("ruleId", JsonTypes::basicTypeToString(JsonTypes::Uuid));
@ -81,14 +100,16 @@ RulesHandler::RulesHandler(QObject *parent) :
setReturns("FindRules", returns); setReturns("FindRules", returns);
params.clear(); returns.clear(); params.clear(); returns.clear();
setDescription("EnableRule", "Enabled a rule that has previously been disabled."); setDescription("EnableRule", "Enabled a rule that has previously been disabled."
"If successfull, the notification \"Rule.RuleConfigurationChanged\" will be emitted.");
params.insert("ruleId", JsonTypes::basicTypeToString(JsonTypes::Uuid)); params.insert("ruleId", JsonTypes::basicTypeToString(JsonTypes::Uuid));
setParams("EnableRule", params); setParams("EnableRule", params);
returns.insert("ruleError", JsonTypes::ruleErrorRef()); returns.insert("ruleError", JsonTypes::ruleErrorRef());
setReturns("EnableRule", returns); setReturns("EnableRule", returns);
params.clear(); returns.clear(); params.clear(); returns.clear();
setDescription("DisableRule", "Disable a rule. The rule won't be triggered by it's events or state changes while it is disabled."); setDescription("DisableRule", "Disable a rule. The rule won't be triggered by it's events or state changes while it is disabled. "
"If successfull, the notification \"Rule.RuleConfigurationChanged\" will be emitted.");
params.insert("ruleId", JsonTypes::basicTypeToString(JsonTypes::Uuid)); params.insert("ruleId", JsonTypes::basicTypeToString(JsonTypes::Uuid));
setParams("DisableRule", params); setParams("DisableRule", params);
returns.insert("ruleError", JsonTypes::ruleErrorRef()); returns.insert("ruleError", JsonTypes::ruleErrorRef());
@ -111,9 +132,15 @@ RulesHandler::RulesHandler(QObject *parent) :
params.insert("active", JsonTypes::basicTypeToString(JsonTypes::Bool)); params.insert("active", JsonTypes::basicTypeToString(JsonTypes::Bool));
setParams("RuleActiveChanged", params); setParams("RuleActiveChanged", params);
params.clear(); returns.clear();
setDescription("RuleConfigurationChanged", "Emitted whenever the configuration of a Rule changed.");
params.insert("rule", JsonTypes::ruleRef());
setParams("RuleConfigurationChanged", params);
connect(GuhCore::instance(), &GuhCore::ruleAdded, this, &RulesHandler::ruleAddedNotification); connect(GuhCore::instance(), &GuhCore::ruleAdded, this, &RulesHandler::ruleAddedNotification);
connect(GuhCore::instance(), &GuhCore::ruleRemoved, this, &RulesHandler::ruleRemovedNotification); connect(GuhCore::instance(), &GuhCore::ruleRemoved, this, &RulesHandler::ruleRemovedNotification);
connect(GuhCore::instance(), &GuhCore::ruleActiveChanged, this, &RulesHandler::ruleActiveChangedNotification); connect(GuhCore::instance(), &GuhCore::ruleActiveChanged, this, &RulesHandler::ruleActiveChangedNotification);
connect(GuhCore::instance(), &GuhCore::ruleConfigurationChanged, this, &RulesHandler::ruleConfigurationChangedNotification);
} }
QString RulesHandler::name() const QString RulesHandler::name() const
@ -149,35 +176,76 @@ JsonReply *RulesHandler::GetRuleDetails(const QVariantMap &params)
JsonReply* RulesHandler::AddRule(const QVariantMap &params) JsonReply* RulesHandler::AddRule(const QVariantMap &params)
{ {
if (params.contains("eventDescriptor") && params.contains("eventDescriptorList")) { // check rule consistency
RuleEngine::RuleError ruleConsistencyError = verifyRuleConsistency(params);
if (ruleConsistencyError != RuleEngine::RuleErrorNoError) {
QVariantMap returns; QVariantMap returns;
qCWarning(dcJsonRpc) << "Only one of eventDesciptor or eventDescriptorList may be used."; returns.insert("ruleError", JsonTypes::ruleErrorToString(ruleConsistencyError));
returns.insert("ruleError", JsonTypes::ruleErrorToString(RuleEngine::RuleErrorInvalidParameter));
return createReply(returns); return createReply(returns);
} }
if (params.contains("eventDescriptor") || params.contains("eventDescriptorList")) { // Check and upack eventDescriptorList
if (params.contains("exitActions")) { QPair<QList<EventDescriptor>, RuleEngine::RuleError> eventDescriptorVerification = verifyEventDescriptors(params);
QVariantMap returns; QList<EventDescriptor> eventDescriptorList = eventDescriptorVerification.first;
qCWarning(dcJsonRpc) << "The exitActions will never be executed if the rule contains an eventDescriptor."; if (eventDescriptorVerification.second != RuleEngine::RuleErrorNoError) {
returns.insert("ruleError", JsonTypes::ruleErrorToString(RuleEngine::RuleErrorInvalidRuleFormat)); QVariantMap returns;
return createReply(returns); returns.insert("ruleError", JsonTypes::ruleErrorToString(eventDescriptorVerification.second));
} return createReply(returns);
} }
// Check and unpack eventDescriptors
QList<EventDescriptor> eventDescriptorList; // Check and unpack stateEvaluator
if (params.contains("eventDescriptor")) { qCDebug(dcJsonRpc) << "unpacking stateEvaluator:" << params.value("stateEvaluator").toMap();
QVariantMap eventMap = params.value("eventDescriptor").toMap(); StateEvaluator stateEvaluator = JsonTypes::unpackStateEvaluator(params.value("stateEvaluator").toMap());
qCDebug(dcJsonRpc) << "unpacking eventDescriptor" << eventMap;
eventDescriptorList.append(JsonTypes::unpackEventDescriptor(eventMap)); // Check and unpack actions
} else if (params.contains("eventDescriptorList")) { QPair<QList<RuleAction>, RuleEngine::RuleError> actionsVerification = verifyActions(params, eventDescriptorList);
QVariantList eventDescriptors = params.value("eventDescriptorList").toList(); QList<RuleAction> actions = actionsVerification.first;
qCDebug(dcJsonRpc) << "unpacking eventDescriptorList:" << eventDescriptors; if (actionsVerification.second != RuleEngine::RuleErrorNoError) {
foreach (const QVariant &eventVariant, eventDescriptors) { QVariantMap returns;
QVariantMap eventMap = eventVariant.toMap(); returns.insert("ruleError", JsonTypes::ruleErrorToString(actionsVerification.second));
eventDescriptorList.append(JsonTypes::unpackEventDescriptor(eventMap)); return createReply(returns);
} }
// Check and unpack exitActions
QPair<QList<RuleAction>, RuleEngine::RuleError> exitActionsVerification = verifyExitActions(params);
QList<RuleAction> exitActions = exitActionsVerification.first;
if (exitActionsVerification.second != RuleEngine::RuleErrorNoError) {
QVariantMap returns;
returns.insert("ruleError", JsonTypes::ruleErrorToString(exitActionsVerification.second));
return createReply(returns);
}
QString name = params.value("name", QString()).toString();
bool enabled = params.value("enabled", true).toBool();
RuleId newRuleId = RuleId::createRuleId();
RuleEngine::RuleError status = GuhCore::instance()->addRule(newRuleId, name, eventDescriptorList, stateEvaluator, actions, exitActions, enabled);
QVariantMap returns;
if (status == RuleEngine::RuleErrorNoError) {
returns.insert("ruleId", newRuleId.toString());
}
returns.insert("ruleError", JsonTypes::ruleErrorToString(status));
return createReply(returns);
}
JsonReply *RulesHandler::EditRule(const QVariantMap &params)
{
// check rule consistency
RuleEngine::RuleError ruleConsistencyError = verifyRuleConsistency(params);
if (ruleConsistencyError != RuleEngine::RuleErrorNoError) {
QVariantMap returns;
returns.insert("ruleError", JsonTypes::ruleErrorToString(ruleConsistencyError));
return createReply(returns);
}
// Check and upack eventDescriptorList
QPair<QList<EventDescriptor>, RuleEngine::RuleError> eventDescriptorVerification = verifyEventDescriptors(params);
QList<EventDescriptor> eventDescriptorList = eventDescriptorVerification.first;
if (eventDescriptorVerification.second != RuleEngine::RuleErrorNoError) {
QVariantMap returns;
returns.insert("ruleError", JsonTypes::ruleErrorToString(eventDescriptorVerification.second));
return createReply(returns);
} }
// Check and unpack stateEvaluator // Check and unpack stateEvaluator
@ -185,97 +253,31 @@ JsonReply* RulesHandler::AddRule(const QVariantMap &params)
StateEvaluator stateEvaluator = JsonTypes::unpackStateEvaluator(params.value("stateEvaluator").toMap()); StateEvaluator stateEvaluator = JsonTypes::unpackStateEvaluator(params.value("stateEvaluator").toMap());
// Check and unpack actions // Check and unpack actions
QList<RuleAction> actions; QPair<QList<RuleAction>, RuleEngine::RuleError> actionsVerification = verifyActions(params, eventDescriptorList);
QVariantList actionList = params.value("actions").toList(); QList<RuleAction> actions = actionsVerification.first;
qCDebug(dcJsonRpc) << "unpacking actions:" << actionList; if (actionsVerification.second != RuleEngine::RuleErrorNoError) {
foreach (const QVariant &actionVariant, actionList) { QVariantMap returns;
QVariantMap actionMap = actionVariant.toMap(); returns.insert("ruleError", JsonTypes::ruleErrorToString(actionsVerification.second));
RuleAction action(ActionTypeId(actionMap.value("actionTypeId").toString()), DeviceId(actionMap.value("deviceId").toString()));
RuleActionParamList actionParamList = JsonTypes::unpackRuleActionParams(actionMap.value("ruleActionParams").toList());
foreach (const RuleActionParam &ruleActionParam, actionParamList) {
if (!ruleActionParam.isValid()) {
qCWarning(dcJsonRpc) << "got an actionParam with value AND eventTypeId!";
QVariantMap returns;
returns.insert("ruleError", JsonTypes::ruleErrorToString(RuleEngine::RuleErrorInvalidRuleActionParameter));
return createReply(returns);
}
}
action.setRuleActionParams(actionParamList);
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;
qCWarning(dcJsonRpc) << "RuleAction" << ruleAction.actionTypeId() << "contains an eventTypeId, but there are no eventDescriptors.";
returns.insert("ruleError", JsonTypes::ruleErrorToString(RuleEngine::RuleErrorInvalidRuleActionParameter));
return createReply(returns);
}
// now check if this eventType is in the eventDescriptorList of this rule
if (!checkEventDescriptors(eventDescriptorList, ruleActionParam.eventTypeId())) {
QVariantMap returns;
qCWarning(dcJsonRpc) << "eventTypeId from RuleAction" << ruleAction.actionTypeId() << "missing in eventDescriptors.";
returns.insert("ruleError", JsonTypes::ruleErrorToString(RuleEngine::RuleErrorInvalidRuleActionParameter));
return createReply(returns);
}
// check if the param type of the event and the action match
QVariant::Type eventParamType = getEventParamType(ruleActionParam.eventTypeId(), ruleActionParam.eventParamName());
QVariant::Type actionParamType = getActionParamType(ruleAction.actionTypeId(), ruleActionParam.name());
if (eventParamType != actionParamType) {
QVariantMap returns;
qCWarning(dcJsonRpc) << "RuleActionParam" << ruleActionParam.name() << " and given event param " << ruleActionParam.eventParamName() << "have not the same type:";
qCWarning(dcJsonRpc) << " -> actionParamType:" << actionParamType;
qCWarning(dcJsonRpc) << " -> eventParamType:" << eventParamType;
returns.insert("ruleError", JsonTypes::ruleErrorToString(RuleEngine::RuleErrorTypesNotMatching));
return createReply(returns);
}
}
}
}
}
QVariantMap returns;
if (actions.count() == 0) {
returns.insert("ruleError", JsonTypes::ruleErrorToString(RuleEngine::RuleErrorMissingParameter));
return createReply(returns); return createReply(returns);
} }
// Check and unpack exitActions // Check and unpack exitActions
QList<RuleAction> exitActions; QPair<QList<RuleAction>, RuleEngine::RuleError> exitActionsVerification = verifyExitActions(params);
if (params.contains("exitActions")) { QList<RuleAction> exitActions = exitActionsVerification.first;
QVariantList exitActionList = params.value("exitActions").toList(); if (exitActionsVerification.second != RuleEngine::RuleErrorNoError) {
qCDebug(dcJsonRpc) << "unpacking exitActions:" << exitActionList; QVariantMap returns;
foreach (const QVariant &actionVariant, exitActionList) { returns.insert("ruleError", JsonTypes::ruleErrorToString(exitActionsVerification.second));
QVariantMap actionMap = actionVariant.toMap(); return createReply(returns);
RuleAction action(ActionTypeId(actionMap.value("actionTypeId").toString()), DeviceId(actionMap.value("deviceId").toString()));
if (action.isEventBased()) {
qCWarning(dcJsonRpc) << "got exitAction with a param value containing an eventTypeId!";
QVariantMap returns;
returns.insert("ruleError", JsonTypes::ruleErrorToString(RuleEngine::RuleErrorInvalidRuleActionParameter));
return createReply(returns);
}
action.setRuleActionParams(JsonTypes::unpackRuleActionParams(actionMap.value("ruleActionParams").toList()));
qCDebug(dcJsonRpc) << "params in exitAction" << action.ruleActionParams();
exitActions.append(action);
}
} }
QString name = params.value("name", QString()).toString(); QString name = params.value("name", QString()).toString();
bool enabled = params.value("enabled", true).toBool(); bool enabled = params.value("enabled", true).toBool();
RuleId newRuleId = RuleId::createRuleId(); RuleId ruleId = RuleId(params.value("ruleId").toString());
RuleEngine::RuleError status = GuhCore::instance()->addRule(newRuleId, name, eventDescriptorList, stateEvaluator, actions, exitActions, enabled); RuleEngine::RuleError status = GuhCore::instance()->editRule(ruleId, name, eventDescriptorList, stateEvaluator, actions, exitActions, enabled);
QVariantMap returns;
if (status == RuleEngine::RuleErrorNoError) { if (status == RuleEngine::RuleErrorNoError) {
returns.insert("ruleId", newRuleId.toString()); returns.insert("ruleId", ruleId.toString());
} }
returns.insert("ruleError", JsonTypes::ruleErrorToString(status)); returns.insert("ruleError", JsonTypes::ruleErrorToString(status));
return createReply(returns); return createReply(returns);
@ -358,6 +360,125 @@ bool RulesHandler::checkEventDescriptors(const QList<EventDescriptor> eventDescr
return false; return false;
} }
RuleEngine::RuleError RulesHandler::verifyRuleConsistency(const QVariantMap &params)
{
// check if there are an eventDescriptor and an eventDescriptorList
if (params.contains("eventDescriptor") && params.contains("eventDescriptorList")) {
qCWarning(dcJsonRpc) << "Only one of eventDesciptor or eventDescriptorList may be used.";
return RuleEngine::RuleErrorInvalidParameter;
}
// check if this rules is based on any event and contains exit actions
if (params.contains("eventDescriptor") || params.contains("eventDescriptorList")) {
if (params.contains("exitActions")) {
qCWarning(dcJsonRpc) << "The exitActions will never be executed if the rule contains an eventDescriptor.";
return RuleEngine::RuleErrorInvalidRuleFormat;
}
}
// check if there are any actions
if (params.value("actions").toList().isEmpty()) {
qCWarning(dcJsonRpc) << "Rule actions missing. A rule without actions has no effect.";
return RuleEngine::RuleErrorMissingParameter;
}
// TODO: check if events and stateEvaluators are missing
return RuleEngine::RuleErrorNoError;
}
QPair<QList<EventDescriptor>, RuleEngine::RuleError> RulesHandler::verifyEventDescriptors(const QVariantMap &params)
{
// Check and unpack eventDescriptors
QList<EventDescriptor> eventDescriptorList = QList<EventDescriptor>();
if (params.contains("eventDescriptor")) {
QVariantMap eventMap = params.value("eventDescriptor").toMap();
qCDebug(dcJsonRpc) << "unpacking eventDescriptor" << eventMap;
eventDescriptorList.append(JsonTypes::unpackEventDescriptor(eventMap));
} else if (params.contains("eventDescriptorList")) {
QVariantList eventDescriptors = params.value("eventDescriptorList").toList();
qCDebug(dcJsonRpc) << "unpacking eventDescriptorList:" << eventDescriptors;
foreach (const QVariant &eventVariant, eventDescriptors) {
QVariantMap eventMap = eventVariant.toMap();
eventDescriptorList.append(JsonTypes::unpackEventDescriptor(eventMap));
}
}
return QPair<QList<EventDescriptor>, RuleEngine::RuleError>(eventDescriptorList, RuleEngine::RuleErrorNoError);
}
QPair<QList<RuleAction>, RuleEngine::RuleError> RulesHandler::verifyActions(const QVariantMap &params, const QList<EventDescriptor> &eventDescriptorList)
{
QList<RuleAction> actions;
QVariantList actionList = params.value("actions").toList();
qCDebug(dcJsonRpc) << "unpacking actions:" << actionList;
foreach (const QVariant &actionVariant, actionList) {
QVariantMap actionMap = actionVariant.toMap();
RuleAction action(ActionTypeId(actionMap.value("actionTypeId").toString()), DeviceId(actionMap.value("deviceId").toString()));
RuleActionParamList actionParamList = JsonTypes::unpackRuleActionParams(actionMap.value("ruleActionParams").toList());
foreach (const RuleActionParam &ruleActionParam, actionParamList) {
if (!ruleActionParam.isValid()) {
qCWarning(dcJsonRpc) << "got an actionParam with value AND eventTypeId!";
return QPair<QList<RuleAction>, RuleEngine::RuleError>(actions, RuleEngine::RuleErrorInvalidRuleActionParameter);
}
}
qCDebug(dcJsonRpc) << "params in exitAction" << action.ruleActionParams();
action.setRuleActionParams(actionParamList);
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()) {
qCWarning(dcJsonRpc) << "RuleAction" << ruleAction.actionTypeId() << "contains an eventTypeId, but there are no eventDescriptors.";
return QPair<QList<RuleAction>, RuleEngine::RuleError>(actions, RuleEngine::RuleErrorInvalidRuleActionParameter);
}
// now check if this eventType is in the eventDescriptorList of this rule
if (!checkEventDescriptors(eventDescriptorList, ruleActionParam.eventTypeId())) {
qCWarning(dcJsonRpc) << "eventTypeId from RuleAction" << ruleAction.actionTypeId() << "missing in eventDescriptors.";
return QPair<QList<RuleAction>, RuleEngine::RuleError>(actions, RuleEngine::RuleErrorInvalidRuleActionParameter);
}
// check if the param type of the event and the action match
QVariant::Type eventParamType = getEventParamType(ruleActionParam.eventTypeId(), ruleActionParam.eventParamName());
QVariant::Type actionParamType = getActionParamType(ruleAction.actionTypeId(), ruleActionParam.name());
if (eventParamType != actionParamType) {
qCWarning(dcJsonRpc) << "RuleActionParam" << ruleActionParam.name() << " and given event param " << ruleActionParam.eventParamName() << "have not the same type:";
qCWarning(dcJsonRpc) << " -> actionParamType:" << actionParamType;
qCWarning(dcJsonRpc) << " -> eventParamType:" << eventParamType;
return QPair<QList<RuleAction>, RuleEngine::RuleError>(actions, RuleEngine::RuleErrorTypesNotMatching);
}
}
}
}
}
return QPair<QList<RuleAction>, RuleEngine::RuleError>(actions, RuleEngine::RuleErrorNoError);
}
QPair<QList<RuleAction>, RuleEngine::RuleError> RulesHandler::verifyExitActions(const QVariantMap &params)
{
QList<RuleAction> exitActions;
if (params.contains("exitActions")) {
QVariantList exitActionList = params.value("exitActions").toList();
qCDebug(dcJsonRpc) << "unpacking exitActions:" << exitActionList;
foreach (const QVariant &actionVariant, exitActionList) {
QVariantMap actionMap = actionVariant.toMap();
RuleAction action(ActionTypeId(actionMap.value("actionTypeId").toString()), DeviceId(actionMap.value("deviceId").toString()));
if (action.isEventBased()) {
qCWarning(dcJsonRpc) << "got exitAction with a param value containing an eventTypeId!";
return QPair<QList<RuleAction>, RuleEngine::RuleError>(exitActions, RuleEngine::RuleErrorInvalidRuleActionParameter);
}
qCDebug(dcJsonRpc) << "params in exitAction" << action.ruleActionParams();
action.setRuleActionParams(JsonTypes::unpackRuleActionParams(actionMap.value("ruleActionParams").toList()));
exitActions.append(action);
}
}
return QPair<QList<RuleAction>, RuleEngine::RuleError>(exitActions, RuleEngine::RuleErrorNoError);
}
void RulesHandler::ruleRemovedNotification(const RuleId &ruleId) void RulesHandler::ruleRemovedNotification(const RuleId &ruleId)
{ {
QVariantMap params; QVariantMap params;
@ -382,3 +503,11 @@ void RulesHandler::ruleActiveChangedNotification(const Rule &rule)
emit RuleActiveChanged(params); emit RuleActiveChanged(params);
} }
void RulesHandler::ruleConfigurationChangedNotification(const Rule &rule)
{
QVariantMap params;
params.insert("rule", JsonTypes::packRule(rule));
emit RuleConfigurationChanged(params);
}

View File

@ -36,6 +36,7 @@ public:
Q_INVOKABLE JsonReply* GetRuleDetails(const QVariantMap &params); Q_INVOKABLE JsonReply* GetRuleDetails(const QVariantMap &params);
Q_INVOKABLE JsonReply* AddRule(const QVariantMap &params); Q_INVOKABLE JsonReply* AddRule(const QVariantMap &params);
Q_INVOKABLE JsonReply* EditRule(const QVariantMap &params);
Q_INVOKABLE JsonReply* RemoveRule(const QVariantMap &params); Q_INVOKABLE JsonReply* RemoveRule(const QVariantMap &params);
Q_INVOKABLE JsonReply* FindRules(const QVariantMap &params); Q_INVOKABLE JsonReply* FindRules(const QVariantMap &params);
@ -46,6 +47,7 @@ signals:
void RuleRemoved(const QVariantMap &params); void RuleRemoved(const QVariantMap &params);
void RuleAdded(const QVariantMap &params); void RuleAdded(const QVariantMap &params);
void RuleActiveChanged(const QVariantMap &params); void RuleActiveChanged(const QVariantMap &params);
void RuleConfigurationChanged(const QVariantMap &params);
private: private:
QVariant::Type getActionParamType(const ActionTypeId &actionTypeId, const QString &paramName); QVariant::Type getActionParamType(const ActionTypeId &actionTypeId, const QString &paramName);
@ -53,10 +55,16 @@ private:
bool checkEventDescriptors(const QList<EventDescriptor> eventDescriptors, const EventTypeId &eventTypeId); bool checkEventDescriptors(const QList<EventDescriptor> eventDescriptors, const EventTypeId &eventTypeId);
RuleEngine::RuleError verifyRuleConsistency(const QVariantMap &params);
QPair<QList<EventDescriptor>, RuleEngine::RuleError> verifyEventDescriptors(const QVariantMap &params);
QPair<QList<RuleAction>, RuleEngine::RuleError> verifyActions(const QVariantMap &params, const QList<EventDescriptor> &eventDescriptorList);
QPair<QList<RuleAction>, RuleEngine::RuleError> verifyExitActions(const QVariantMap &params);
private slots: private slots:
void ruleRemovedNotification(const RuleId &ruleId); void ruleRemovedNotification(const RuleId &ruleId);
void ruleAddedNotification(const Rule &rule); void ruleAddedNotification(const Rule &rule);
void ruleActiveChangedNotification(const Rule &rule); void ruleActiveChangedNotification(const Rule &rule);
void ruleConfigurationChangedNotification(const Rule &rule);
}; };

View File

@ -42,6 +42,10 @@
\a ruleId holds the id of the removed rule. You should remove any references \a ruleId holds the id of the removed rule. You should remove any references
or copies you hold for this rule.*/ or copies you hold for this rule.*/
/*! \fn void RuleEngine::ruleConfigurationChanged(const RuleId &ruleId)
Will be emitted whenever a \l{Rule} changed his enable/disable status.
\a ruleId holds the id of the changed rule.*/
/*! \enum RuleEngine::RuleError /*! \enum RuleEngine::RuleError
\value RuleErrorNoError \value RuleErrorNoError
No error happened. Everything is fine. No error happened. Everything is fine.
@ -255,8 +259,10 @@ RuleEngine::RuleError RuleEngine::addRule(const RuleId &ruleId, const QString &n
return addRule(ruleId, name, eventDescriptorList, StateEvaluator(), actions, QList<RuleAction>(), enabled); return addRule(ruleId, name, eventDescriptorList, StateEvaluator(), actions, QList<RuleAction>(), 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.*/ /*! 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<EventDescriptor> &eventDescriptorList, const StateEvaluator &stateEvaluator, const QList<RuleAction> &actions, const QList<RuleAction> &exitActions, bool enabled) If \a fromEdit is true, the notification Rules.RuleAdded will not be emitted.
*/
RuleEngine::RuleError RuleEngine::addRule(const RuleId &ruleId, const QString &name, const QList<EventDescriptor> &eventDescriptorList, const StateEvaluator &stateEvaluator, const QList<RuleAction> &actions, const QList<RuleAction> &exitActions, bool enabled, bool fromEdit)
{ {
if (ruleId.isNull()) { if (ruleId.isNull()) {
return RuleErrorInvalidRuleId; return RuleErrorInvalidRuleId;
@ -266,8 +272,6 @@ RuleEngine::RuleError RuleEngine::addRule(const RuleId &ruleId, const QString &n
return RuleErrorInvalidRuleId; return RuleErrorInvalidRuleId;
} }
// TODO: check rule name for duplicated rulesnames
foreach (const EventDescriptor &eventDescriptor, eventDescriptorList) { foreach (const EventDescriptor &eventDescriptor, eventDescriptorList) {
Device *device = GuhCore::instance()->findConfiguredDevice(eventDescriptor.deviceId()); Device *device = GuhCore::instance()->findConfiguredDevice(eventDescriptor.deviceId());
if (!device) { if (!device) {
@ -337,70 +341,37 @@ RuleEngine::RuleError RuleEngine::addRule(const RuleId &ruleId, const QString &n
Rule rule = Rule(ruleId, name, eventDescriptorList, stateEvaluator, actions, exitActions); Rule rule = Rule(ruleId, name, eventDescriptorList, stateEvaluator, actions, exitActions);
rule.setEnabled(enabled); rule.setEnabled(enabled);
appendRule(rule); appendRule(rule);
emit ruleAdded(rule); saveRule(rule);
if (!fromEdit)
emit ruleAdded(rule);
// Save Events / EventDescriptors return RuleErrorNoError;
QSettings settings(m_settingsFile); }
settings.beginGroup(rule.id().toString());
settings.setValue("name", name);
settings.setValue("enabled", enabled);
settings.beginGroup("events");
for (int i = 0; i < eventDescriptorList.count(); i++) {
const EventDescriptor &eventDescriptor = eventDescriptorList.at(i);
settings.beginGroup("EventDescriptor-" + QString::number(i));
settings.setValue("deviceId", eventDescriptor.deviceId().toString());
settings.setValue("eventTypeId", eventDescriptor.eventTypeId().toString());
foreach (const ParamDescriptor &paramDescriptor, eventDescriptor.paramDescriptors()) { RuleEngine::RuleError RuleEngine::editRule(const RuleId &ruleId, const QString &name, const QList<EventDescriptor> &eventDescriptorList, const StateEvaluator &stateEvaluator, const QList<RuleAction> &actions, const QList<RuleAction> &exitActions, bool enabled)
settings.beginGroup("ParamDescriptor-" + paramDescriptor.name()); {
settings.setValue("value", paramDescriptor.value()); if (ruleId.isNull()) {
settings.setValue("operator", paramDescriptor.operatorType()); return RuleErrorInvalidRuleId;
settings.endGroup();
}
settings.endGroup();
} }
settings.endGroup();
// Save StateEvaluator if (findRule(ruleId).id().isNull()) {
stateEvaluator.dumpToSettings(settings, "stateEvaluator"); qCWarning(dcRuleEngine) << "Cannot edit rule. There is no rule with id:" << ruleId.toString();
return RuleErrorRuleNotFound;
// Save ruleActions
int i = 0;
settings.beginGroup("ruleActions");
foreach (const RuleAction &action, rule.actions()) {
settings.beginGroup(QString::number(i));
settings.setValue("deviceId", action.deviceId().toString());
settings.setValue("actionTypeId", action.actionTypeId().toString());
foreach (const RuleActionParam &param, action.ruleActionParams()) {
settings.beginGroup("RuleActionParam-" + param.name());
settings.setValue("value", param.value());
if (param.eventTypeId() != EventTypeId()) {
settings.setValue("eventTypeId", param.eventTypeId().toString());
settings.setValue("eventParamName", param.eventParamName());
}
settings.endGroup();
}
i++;
settings.endGroup();
} }
settings.endGroup();
// Save ruleExitActions // first remove old rule with this id
settings.beginGroup("ruleExitActions"); RuleError removeResult = removeRule(ruleId, true);
i = 0; if (removeResult != RuleErrorNoError) {
foreach (const RuleAction &action, rule.exitActions()) { return removeResult;
settings.beginGroup(QString::number(i));
settings.setValue("deviceId", action.deviceId().toString());
settings.setValue("actionTypeId", action.actionTypeId().toString());
foreach (const RuleActionParam &param, action.ruleActionParams()) {
settings.beginGroup("RuleActionParam-" + param.name());
settings.setValue("value", param.value());
settings.endGroup();
}
i++;
settings.endGroup();
} }
settings.endGroup();
// the rule is removed, now add it with the same id and new vonfiguration
RuleError addResult = addRule(ruleId, name, eventDescriptorList, stateEvaluator, actions, exitActions, enabled, true);
if (addResult != RuleErrorNoError) {
return addResult;
}
emit ruleConfigurationChanged(m_rules.value(ruleId));
return RuleErrorNoError; return RuleErrorNoError;
} }
@ -422,8 +393,10 @@ QList<RuleId> RuleEngine::ruleIds() const
/*! Removes the \l{Rule} with the given \a ruleId from the Engine. /*! Removes the \l{Rule} with the given \a ruleId from the Engine.
Returns \l{RuleError} which describes whether the operation Returns \l{RuleError} which describes whether the operation
was successful or not. */ was successful or not. If \a fromEdit is true, the notification Rules.RuleRemoved
RuleEngine::RuleError RuleEngine::removeRule(const RuleId &ruleId) will not be emitted.
*/
RuleEngine::RuleError RuleEngine::removeRule(const RuleId &ruleId, bool fromEdit)
{ {
int index = m_ruleIds.indexOf(ruleId); int index = m_ruleIds.indexOf(ruleId);
@ -439,7 +412,9 @@ RuleEngine::RuleError RuleEngine::removeRule(const RuleId &ruleId)
settings.remove(""); settings.remove("");
settings.endGroup(); settings.endGroup();
emit ruleRemoved(ruleId); if (!fromEdit)
emit ruleRemoved(ruleId);
return RuleErrorNoError; return RuleErrorNoError;
} }
@ -454,13 +429,9 @@ RuleEngine::RuleError RuleEngine::enableRule(const RuleId &ruleId)
Rule rule = m_rules.value(ruleId); Rule rule = m_rules.value(ruleId);
rule.setEnabled(true); rule.setEnabled(true);
m_rules[ruleId] = rule; m_rules[ruleId] = rule;
QSettings settings(m_settingsFile);
settings.beginGroup(ruleId.toString()); saveRule(rule);
if (!settings.value("enabled", true).toBool()) { emit ruleConfigurationChanged(rule);
settings.setValue("enabled", true);
emit ruleChanged(ruleId);
}
settings.endGroup();
return RuleErrorNoError; return RuleErrorNoError;
} }
@ -476,14 +447,8 @@ RuleEngine::RuleError RuleEngine::disableRule(const RuleId &ruleId)
Rule rule = m_rules.value(ruleId); Rule rule = m_rules.value(ruleId);
rule.setEnabled(false); rule.setEnabled(false);
m_rules[ruleId] = rule; m_rules[ruleId] = rule;
QSettings settings(m_settingsFile); saveRule(rule);
settings.beginGroup(ruleId.toString()); emit ruleConfigurationChanged(rule);
if (settings.value("enabled", true).toBool()) {
settings.setValue("enabled", false);
emit ruleChanged(ruleId);
}
settings.endGroup();
return RuleErrorNoError; return RuleErrorNoError;
} }
@ -591,3 +556,69 @@ void RuleEngine::appendRule(const Rule &rule)
m_rules.insert(rule.id(), rule); m_rules.insert(rule.id(), rule);
m_ruleIds.append(rule.id()); m_ruleIds.append(rule.id());
} }
void RuleEngine::saveRule(const Rule &rule)
{
// Save Events / EventDescriptors
QSettings settings(m_settingsFile);
settings.beginGroup(rule.id().toString());
settings.setValue("name", rule.name());
settings.setValue("enabled", rule.enabled());
settings.beginGroup("events");
for (int i = 0; i < rule.eventDescriptors().count(); i++) {
const EventDescriptor &eventDescriptor = rule.eventDescriptors().at(i);
settings.beginGroup("EventDescriptor-" + QString::number(i));
settings.setValue("deviceId", eventDescriptor.deviceId().toString());
settings.setValue("eventTypeId", eventDescriptor.eventTypeId().toString());
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();
// Save StateEvaluator
rule.stateEvaluator().dumpToSettings(settings, "stateEvaluator");
// Save ruleActions
int i = 0;
settings.beginGroup("ruleActions");
foreach (const RuleAction &action, rule.actions()) {
settings.beginGroup(QString::number(i));
settings.setValue("deviceId", action.deviceId().toString());
settings.setValue("actionTypeId", action.actionTypeId().toString());
foreach (const RuleActionParam &param, action.ruleActionParams()) {
settings.beginGroup("RuleActionParam-" + param.name());
settings.setValue("value", param.value());
if (param.eventTypeId() != EventTypeId()) {
settings.setValue("eventTypeId", param.eventTypeId().toString());
settings.setValue("eventParamName", param.eventParamName());
}
settings.endGroup();
}
i++;
settings.endGroup();
}
settings.endGroup();
// Save ruleExitActions
settings.beginGroup("ruleExitActions");
i = 0;
foreach (const RuleAction &action, rule.exitActions()) {
settings.beginGroup(QString::number(i));
settings.setValue("deviceId", action.deviceId().toString());
settings.setValue("actionTypeId", action.actionTypeId().toString());
foreach (const RuleActionParam &param, action.ruleActionParams()) {
settings.beginGroup("RuleActionParam-" + param.name());
settings.setValue("value", param.value());
settings.endGroup();
}
i++;
settings.endGroup();
}
settings.endGroup();
}

View File

@ -60,11 +60,14 @@ public:
QList<Rule> evaluateEvent(const Event &event); QList<Rule> evaluateEvent(const Event &event);
RuleError addRule(const RuleId &ruleId, const QString &name, const QList<EventDescriptor> &eventDescriptorList, const QList<RuleAction> &actions, bool enabled = true); RuleError addRule(const RuleId &ruleId, const QString &name, const QList<EventDescriptor> &eventDescriptorList, const QList<RuleAction> &actions, bool enabled = true);
RuleError addRule(const RuleId &ruleId, const QString &name, const QList<EventDescriptor> &eventDescriptorList, const StateEvaluator &stateEvaluator, const QList<RuleAction> &actions, const QList<RuleAction> &exitActions, bool enabled = true); RuleError addRule(const RuleId &ruleId, const QString &name, const QList<EventDescriptor> &eventDescriptorList, const StateEvaluator &stateEvaluator, const QList<RuleAction> &actions, const QList<RuleAction> &exitActions, bool enabled = true, bool fromEdit = false);
RuleError editRule(const RuleId &ruleId, const QString &name, const QList<EventDescriptor> &eventDescriptorList, const StateEvaluator &stateEvaluator, const QList<RuleAction> &actions, const QList<RuleAction> &exitActions, bool enabled = true);
QList<Rule> rules() const; QList<Rule> rules() const;
QList<RuleId> ruleIds() const; QList<RuleId> ruleIds() const;
RuleError removeRule(const RuleId &ruleId); RuleError removeRule(const RuleId &ruleId, bool fromEdit = false);
RuleError enableRule(const RuleId &ruleId); RuleError enableRule(const RuleId &ruleId);
RuleError disableRule(const RuleId &ruleId); RuleError disableRule(const RuleId &ruleId);
@ -77,13 +80,14 @@ public:
signals: signals:
void ruleAdded(const Rule &rule); void ruleAdded(const Rule &rule);
void ruleRemoved(const RuleId &ruleId); void ruleRemoved(const RuleId &ruleId);
void ruleChanged(const RuleId &ruleId); void ruleConfigurationChanged(const Rule &rule);
private: private:
bool containsEvent(const Rule &rule, const Event &event); bool containsEvent(const Rule &rule, const Event &event);
bool containsState(const StateEvaluator &stateEvaluator, const Event &stateChangeEvent); bool containsState(const StateEvaluator &stateEvaluator, const Event &stateChangeEvent);
void appendRule(const Rule &rule); void appendRule(const Rule &rule);
void saveRule(const Rule &rule);
private: private:
QString m_settingsFile; QString m_settingsFile;