diff --git a/libhive/device.cpp b/libhive/device.cpp index 7b486fa2..080a8dca 100644 --- a/libhive/device.cpp +++ b/libhive/device.cpp @@ -62,3 +62,25 @@ void Device::setStates(const QList &states) { m_states = states; } + +QVariant Device::stateValue(const QUuid &stateTypeId) const +{ + foreach (const State &state, m_states) { + if (state.stateTypeId() == stateTypeId) { + return state.value(); + } + } + return QVariant(); +} + +void Device::setStateValue(const QUuid &stateTypeId, const QVariant &value) +{ + for (int i = 0; i < m_states.count(); ++i) { + if (m_states.at(i).stateTypeId() == stateTypeId) { + State newState(stateTypeId, m_id); + newState.setValue(value); + m_states[i] = newState; + return; + } + } +} diff --git a/libhive/device.h b/libhive/device.h index 1a615f14..76625900 100644 --- a/libhive/device.h +++ b/libhive/device.h @@ -27,6 +27,9 @@ public: QList states() const; void setStates(const QList &states); + QVariant stateValue(const QUuid &stateTypeId) const; + void setStateValue(const QUuid &stateTypeId, const QVariant &value); + private: Device(const QUuid &pluginId, const QUuid &id, const QUuid &deviceClassId, QObject *parent = 0); Device(const QUuid &pluginId, const QUuid &deviceClassId, QObject *parent = 0); diff --git a/libhive/state.cpp b/libhive/state.cpp index 6a9b7aff..6533b4f6 100644 --- a/libhive/state.cpp +++ b/libhive/state.cpp @@ -1,5 +1,25 @@ #include "state.h" -State::State(const QUuid &stateTypeId) +State::State(const QUuid &stateTypeId, const QUuid &deviceId) { } + +QUuid State::stateTypeId() const +{ + return m_stateTypeId; +} + +QUuid State::deviceId() const +{ + return m_deviceId; +} + +QVariant State::value() const +{ + return m_value; +} + +void State::setValue(const QVariant &value) +{ + m_value = value; +} diff --git a/libhive/state.h b/libhive/state.h index 51ab16cd..48ff04f3 100644 --- a/libhive/state.h +++ b/libhive/state.h @@ -7,15 +7,17 @@ class State { public: - State(const QUuid &stateTypeId); + State(const QUuid &stateTypeId, const QUuid &deviceId); QUuid stateTypeId() const; + QUuid deviceId() const; QVariant value() const; void setValue(const QVariant &value); private: QUuid m_stateTypeId; + QUuid m_deviceId; QVariant m_value; }; diff --git a/server/jsonrpcserver.cpp b/server/jsonrpcserver.cpp index 900dfe0e..e40a4cfa 100644 --- a/server/jsonrpcserver.cpp +++ b/server/jsonrpcserver.cpp @@ -129,7 +129,12 @@ void JsonRPCServer::handleRulesMessage(int clientId, int commandId, const QStrin QVariantMap ruleMap; ruleMap.insert("id", rule.id()); ruleMap.insert("trigger", packTrigger(rule.trigger())); - ruleMap.insert("action", packAction(rule.action())); + QVariantList actionList; + foreach (const Action &action, rule.actions()) { + actionList.append(packAction(action)); + } + + ruleMap.insert("actions", actionList); rulesList.append(ruleMap); } QVariantMap rspParams; @@ -143,12 +148,17 @@ void JsonRPCServer::handleRulesMessage(int clientId, int commandId, const QStrin QVariantMap triggerParams = triggerMap.value("params").toMap(); Trigger trigger(triggerTypeId, triggerDeviceId, triggerParams); - QVariantMap actionMap = params.value("action").toMap(); - Action action(actionMap.value("deviceId").toString()); - action.setName(actionMap.value("name").toString()); - action.setParams(actionMap.value("params").toMap()); + QList actions; + QVariantList actionList = params.value("actions").toList(); + foreach (const QVariant &actionVariant, actionList) { + QVariantMap actionMap = actionVariant.toMap(); + Action action(actionMap.value("deviceId").toString()); + action.setName(actionMap.value("name").toString()); + action.setParams(actionMap.value("params").toMap()); + actions.append(action); + } - switch(HiveCore::instance()->ruleEngine()->addRule(trigger, action)) { + switch(HiveCore::instance()->ruleEngine()->addRule(trigger, actions)) { case RuleEngine::RuleErrorNoError: sendResponse(clientId, commandId); break; diff --git a/server/rule.cpp b/server/rule.cpp index 906784cd..8d02b203 100644 --- a/server/rule.cpp +++ b/server/rule.cpp @@ -1,9 +1,10 @@ #include "rule.h" -Rule::Rule(const QUuid &id, const Trigger &trigger, const Action &action): +Rule::Rule(const QUuid &id, const Trigger &trigger, const QList states, const QList &actions): m_id(id), m_trigger(trigger), - m_action(action) + m_states(states), + m_actions(actions) { } @@ -17,7 +18,12 @@ Trigger Rule::trigger() const return m_trigger; } -Action Rule::action() const +QList Rule::states() const { - return m_action; + return m_states; +} + +QList Rule::actions() const +{ + return m_actions; } diff --git a/server/rule.h b/server/rule.h index 9f4ab15c..7a3f2be1 100644 --- a/server/rule.h +++ b/server/rule.h @@ -1,6 +1,7 @@ #ifndef RULE_H #define RULE_H +#include "state.h" #include "action.h" #include "trigger.h" @@ -9,16 +10,18 @@ class Rule { public: - Rule(const QUuid &id, const Trigger &trigger, const Action &action); + Rule(const QUuid &id, const Trigger &trigger, const QList states, const QList &actions); QUuid id() const; Trigger trigger() const; - Action action() const; + QList states() const; + QList actions() const; private: QUuid m_id; Trigger m_trigger; - Action m_action; + QList m_states; + QList m_actions; }; #endif // RULE_H diff --git a/server/ruleengine.cpp b/server/ruleengine.cpp index 7fe0eff5..76879f3c 100644 --- a/server/ruleengine.cpp +++ b/server/ruleengine.cpp @@ -25,14 +25,31 @@ RuleEngine::RuleEngine(QObject *parent) : Trigger trigger(settings.value("triggerTypeId").toUuid(), settings.value("deviceId").toUuid(), settings.value("params").toMap()); settings.endGroup(); - settings.beginGroup("action"); - Action action = Action(settings.value("deviceId").toUuid(), settings.value("id").toUuid()); - action.setName(settings.value("name").toString()); - action.setParams(settings.value("params").toMap()); - settings.endGroup(); + settings.beginGroup("states"); + QList states; + foreach (const QString &stateTypeIdString, settings.childGroups()) { + settings.beginGroup(stateTypeIdString); + State state(stateTypeIdString, settings.value("deviceId").toUuid()); + state.setValue(settings.value("value")); + settings.endGroup(); + states.append(state); + } settings.endGroup(); - Rule rule = Rule(QUuid(idString), trigger, action); + settings.beginGroup("actions"); + QList actions; + foreach (const QString &actionIdString, settings.childGroups()) { + settings.beginGroup(actionIdString); + Action action = Action(settings.value("deviceId").toUuid(), settings.value("id").toUuid()); + action.setName(settings.value("name").toString()); + action.setParams(settings.value("params").toMap()); + settings.endGroup(); + } + settings.endGroup(); + + settings.endGroup(); + + Rule rule = Rule(QUuid(idString), trigger, states, actions); m_rules.append(rule); } @@ -43,15 +60,35 @@ QList RuleEngine::evaluateTrigger(const Trigger &trigger) QList actions; for (int i = 0; i < m_rules.count(); ++i) { if (m_rules.at(i).trigger() == trigger) { - actions << m_rules.at(i).action(); + bool statesMatching = true; + foreach (const State &state, m_rules.at(i).states()) { + Device *device = HiveCore::instance()->deviceManager()->findConfiguredDevice(state.deviceId()); + if (!device) { + qWarning() << "Device referenced in rule cannot be found"; + break; + } + if (state.value() != device->stateValue(state.stateTypeId())) { + statesMatching = false; + break; + } + } + + if (statesMatching) { + actions.append(m_rules.at(i).actions()); + } } } return actions; } -RuleEngine::RuleError RuleEngine::addRule(const Trigger &trigger, const Action &action) +RuleEngine::RuleError RuleEngine::addRule(const Trigger &trigger, const QList &actions) { - qDebug() << "adding rule: Trigger:" << trigger.triggerTypeId() << "deviceid:" << action.deviceId(); + return addRule(trigger, QList(), actions); +} + +RuleEngine::RuleError RuleEngine::addRule(const Trigger &trigger, const QList states, const QList &actions) +{ + qDebug() << "adding rule: Trigger:" << trigger.triggerTypeId() << "with" << actions.count() << "actions"; DeviceClass triggerDeviceClass = HiveCore::instance()->deviceManager()->findDeviceClassforTrigger(trigger.triggerTypeId()); Device *device = HiveCore::instance()->deviceManager()->findConfiguredDevice(trigger.deviceId()); @@ -73,7 +110,7 @@ RuleEngine::RuleError RuleEngine::addRule(const Trigger &trigger, const Action & return RuleErrorTriggerTypeNotFound; } - Rule rule = Rule(QUuid::createUuid(), trigger, action); + Rule rule = Rule(QUuid::createUuid(), trigger, states, actions); m_rules.append(rule); QSettings settings(rulesFileName); @@ -83,11 +120,26 @@ RuleEngine::RuleError RuleEngine::addRule(const Trigger &trigger, const Action & settings.setValue("deviceId", trigger.deviceId()); settings.setValue("params", trigger.params()); settings.endGroup(); - settings.beginGroup("action"); - settings.setValue("id", rule.action().id()); - settings.setValue("deviceId", rule.action().deviceId()); - settings.setValue("name", rule.action().name()); - settings.setValue("params", rule.action().params()); + + 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(); + + settings.beginGroup("actions"); + foreach (const Action &action, rule.actions()) { + settings.beginGroup(action.id().toString()); + settings.setValue("deviceId", action.deviceId()); + settings.setValue("name", action.name()); + settings.setValue("params", action.params()); + settings.endGroup(); + } + settings.endGroup(); return RuleErrorNoError; diff --git a/server/ruleengine.h b/server/ruleengine.h index eb37240f..4af5d3b0 100644 --- a/server/ruleengine.h +++ b/server/ruleengine.h @@ -22,7 +22,8 @@ public: QList evaluateTrigger(const Trigger &trigger); - RuleError addRule(const Trigger &trigger, const Action &action); + RuleError addRule(const Trigger &trigger, const QList &actions); + RuleError addRule(const Trigger &trigger, const QList states, const QList &actions); QList rules() const; private: