A little more work on browser item support for rules

pull/183/head
Michael Zanetti 2019-07-17 20:48:16 +02:00
parent 4e7557f964
commit 0fb42681af
12 changed files with 120 additions and 77 deletions

View File

@ -184,6 +184,7 @@ void JsonTypes::init()
s_ruleAction.insert("o:actionTypeId", basicTypeToString(Uuid));
s_ruleAction.insert("o:interface", basicTypeToString(String));
s_ruleAction.insert("o:interfaceAction", basicTypeToString(String));
s_ruleAction.insert("o:browserItemId", basicTypeToString(String));
s_ruleAction.insert("o:ruleActionParams", QVariantList() << ruleActionParamRef());
// RuleActionParam
@ -617,8 +618,11 @@ QVariantMap JsonTypes::packRuleAction(const RuleAction &ruleAction)
{
QVariantMap variant;
if (ruleAction.type() == RuleAction::TypeDevice) {
variant.insert("actionTypeId", ruleAction.actionTypeId().toString());
variant.insert("deviceId", ruleAction.deviceId().toString());
variant.insert("actionTypeId", ruleAction.actionTypeId().toString());
} else if (ruleAction.type() == RuleAction::TypeBrowser) {
variant.insert("deviceId", ruleAction.deviceId().toString());
variant.insert("browserItemId", ruleAction.browserItemId());
} else {
variant.insert("interface", ruleAction.interface());
variant.insert("interfaceAction", ruleAction.interfaceAction());
@ -1500,10 +1504,13 @@ RuleAction JsonTypes::unpackRuleAction(const QVariantMap &ruleActionMap)
DeviceId actionDeviceId(ruleActionMap.value("deviceId").toString());
QString interface = ruleActionMap.value("interface").toString();
QString interfaceAction = ruleActionMap.value("interfaceAction").toString();
QString browserItemId = ruleActionMap.value("browserItemId").toString();
RuleActionParamList actionParamList = JsonTypes::unpackRuleActionParams(ruleActionMap.value("ruleActionParams").toList());
if (!actionTypeId.isNull() && !actionDeviceId.isNull()) {
if (!actionDeviceId.isNull() && !actionTypeId.isNull()) {
return RuleAction(actionTypeId, actionDeviceId, actionParamList);
} else if (!actionDeviceId.isNull() && !browserItemId.isNull()) {
return RuleAction(actionDeviceId, browserItemId);
}
return RuleAction(interface, interfaceAction, actionParamList);
}

View File

@ -18,9 +18,11 @@ RESOURCES += $$top_srcdir/icons.qrc \
HEADERS += nymeacore.h \
devices/devicemanagerimplementation.h \
devices/translator.h \
devices/stateevaluator.h \
ruleengine/ruleengine.h \
ruleengine/rule.h \
ruleengine/stateevaluator.h \
ruleengine/ruleaction.h \
ruleengine/ruleactionparam.h \
transportinterface.h \
nymeaconfiguration.h \
servermanager.h \
@ -102,9 +104,11 @@ HEADERS += nymeacore.h \
SOURCES += nymeacore.cpp \
devices/devicemanagerimplementation.cpp \
devices/translator.cpp \
devices/stateevaluator.cpp \
ruleengine/ruleengine.cpp \
ruleengine/rule.cpp \
ruleengine/stateevaluator.cpp \
ruleengine/ruleaction.cpp \
ruleengine/ruleactionparam.cpp \
transportinterface.cpp \
nymeaconfiguration.cpp \
servermanager.cpp \

View File

@ -478,9 +478,14 @@ Device::DeviceError NymeaCore::executeBrowserItemAction(const BrowserItemAction
void NymeaCore::executeRuleActions(const QList<RuleAction> ruleActions)
{
QList<Action> actions;
QList<BrowserAction> browserActions;
foreach (const RuleAction &ruleAction, ruleActions) {
if (ruleAction.type() == RuleAction::TypeDevice) {
Device *device = m_deviceManager->findConfiguredDevice(ruleAction.deviceId());
if (!device) {
qCWarning(dcRuleEngine()) << "Unable to find device" << ruleAction.deviceId() << "for rule action" << ruleAction;
continue;
}
ActionTypeId actionTypeId = ruleAction.actionTypeId();
ParamList params;
bool ok = true;
@ -510,6 +515,14 @@ void NymeaCore::executeRuleActions(const QList<RuleAction> ruleActions)
Action action(actionTypeId, device->id());
action.setParams(params);
actions.append(action);
} else if (ruleAction.type() == RuleAction::TypeBrowser) {
Device *device = m_deviceManager->findConfiguredDevice(ruleAction.deviceId());
if (!device) {
qCWarning(dcRuleEngine()) << "Unable to find device" << ruleAction.deviceId() << "for rule action" << ruleAction;
continue;
}
BrowserAction browserAction(ruleAction.deviceId(), ruleAction.browserItemId());
browserActions.append(browserAction);
} else {
QList<Device*> devices = m_deviceManager->findConfiguredDevices(ruleAction.interface());
foreach (Device* device, devices) {
@ -581,6 +594,25 @@ void NymeaCore::executeRuleActions(const QList<RuleAction> ruleActions)
// if (status != Device::DeviceErrorAsync)
// m_logger->logAction(action, status == Device::DeviceErrorNoError ? Logging::LoggingLevelInfo : Logging::LoggingLevelAlert, status);
}
foreach (const BrowserAction &browserAction, browserActions) {
Device::DeviceError status = executeBrowserItem(browserAction);
switch(status) {
case Device::DeviceErrorNoError:
break;
case Device::DeviceErrorSetupFailed:
qCWarning(dcRuleEngine) << "Error executing action. Device setup failed.";
break;
case Device::DeviceErrorAsync:
qCDebug(dcRuleEngine) << "Executing asynchronous action.";
break;
case Device::DeviceErrorInvalidParameter:
qCWarning(dcRuleEngine) << "Error executing action. Invalid action parameter.";
break;
default:
qCWarning(dcRuleEngine) << "Error executing action:" << status;
}
}
}
/*! Calls the metheod RuleEngine::removeRule(\a id).

View File

@ -112,7 +112,7 @@ RuleAction::Type RuleAction::type() const
if (!m_deviceId.isNull() && !m_actionTypeId.isNull()) {
return TypeDevice;
}
if (!m_deviceId.isNull() && m_browserItemId.isEmpty()) {
if (!m_deviceId.isNull() && !m_browserItemId.isEmpty()) {
return TypeBrowser;
}
if (!m_interface.isEmpty() && !m_interfaceAction.isEmpty()) {

View File

@ -25,9 +25,9 @@
#define RULEACTION_H
#include "libnymea.h"
#include "action.h"
#include "types/action.h"
#include "types/browseritemaction.h"
#include "ruleactionparam.h"
#include "browseritemaction.h"
class LIBNYMEA_EXPORT RuleAction
{

View File

@ -28,7 +28,7 @@
#include <QString>
#include <QVariant>
#include "param.h"
#include "types/param.h"
#include "libnymea.h"
#include "typeutils.h"

View File

@ -912,7 +912,7 @@ bool RuleEngine::containsState(const StateEvaluator &stateEvaluator, const Event
RuleEngine::RuleError RuleEngine::checkRuleAction(const RuleAction &ruleAction, const Rule &rule)
{
if (!ruleAction.isValid()) {
qWarning(dcRuleEngine()) << "Action is incomplete. It must have either actionTypeId and deviceId, or interface and interfaceAction";
qWarning(dcRuleEngine()) << "Action is incomplete. It must have either deviceId and actionTypeId/browserItemId, or interface and interfaceAction:" << ruleAction;
return RuleErrorActionTypeNotFound;
}
@ -920,7 +920,7 @@ RuleEngine::RuleError RuleEngine::checkRuleAction(const RuleAction &ruleAction,
if (ruleAction.type() == RuleAction::TypeDevice) {
Device *device = NymeaCore::instance()->deviceManager()->findConfiguredDevice(ruleAction.deviceId());
if (!device) {
qCWarning(dcRuleEngine) << "Cannot create rule. No configured device for action with actionTypeId" << ruleAction.actionTypeId();
qCWarning(dcRuleEngine) << "Cannot create rule. No configured device with ID" << ruleAction.deviceId();
return RuleErrorDeviceNotFound;
}
@ -942,10 +942,23 @@ RuleEngine::RuleError RuleEngine::checkRuleAction(const RuleAction &ruleAction,
qCWarning(dcRuleEngine()) << "Cannot create rule. Interface" << iface.name() << "does not implement action" << ruleAction.interfaceAction();
return RuleError::RuleErrorActionTypeNotFound;
}
} else if (ruleAction.type() == RuleAction::TypeBrowser) {
Device *device = NymeaCore::instance()->deviceManager()->findConfiguredDevice(ruleAction.deviceId());
if (!device) {
qCWarning(dcRuleEngine) << "Cannot create rule. No configured device with ID" << ruleAction.deviceId();
return RuleErrorDeviceNotFound;
}
if (ruleAction.browserItemId().isEmpty()) {
qCWarning(dcRuleEngine()) << "Cannot create rule with empty browserItemId";
return RuleErrorInvalidRuleActionParameter;
}
} else {
return RuleErrorActionTypeNotFound;
}
// Not all rule actions might have an actiontype (e.g. browser item executions)
if (!actionType.id().isNull()) {
// Verify given params
foreach (const RuleActionParam &ruleActionParam, ruleAction.ruleActionParams()) {
RuleError ruleActionParamError = checkRuleActionParam(ruleActionParam, actionType, rule);
@ -968,6 +981,7 @@ RuleEngine::RuleError RuleEngine::checkRuleAction(const RuleAction &ruleAction,
return RuleErrorMissingParameter;
}
}
}
return RuleErrorNoError;
}
@ -1190,66 +1204,54 @@ void RuleEngine::saveRule(const Rule &rule)
rule.stateEvaluator().dumpToSettings(settings, "stateEvaluator");
// Save ruleActions
int i = 0;
settings.beginGroup("ruleActions");
foreach (const RuleAction &action, rule.actions()) {
settings.beginGroup(QString::number(i));
if (!action.deviceId().isNull() && !action.actionTypeId().isNull()) {
settings.setValue("deviceId", action.deviceId().toString());
settings.setValue("actionTypeId", action.actionTypeId().toString());
} else {
settings.setValue("interface", action.interface());
settings.setValue("interfaceAction", action.interfaceAction());
}
foreach (const RuleActionParam &param, action.ruleActionParams()) {
if (!param.paramTypeId().isNull()) {
settings.beginGroup("RuleActionParam-" + param.paramTypeId().toString());
} else {
settings.beginGroup("RuleActionParam-" + param.paramName());
}
settings.setValue("valueType", static_cast<int>(param.value().type()));
settings.setValue("value", param.value());
if (param.isEventBased()) {
settings.setValue("eventTypeId", param.eventTypeId().toString());
settings.setValue("eventParamTypeId", param.eventParamTypeId());
} else if (param.isStateBased()) {
settings.setValue("stateDeviceId", param.stateDeviceId().toString());
settings.setValue("stateTypeId", param.stateTypeId());
}
settings.endGroup();
}
i++;
settings.endGroup();
}
saveRuleActions(&settings, rule.actions());
settings.endGroup();
// Save ruleExitActions
settings.beginGroup("ruleExitActions");
i = 0;
foreach (const RuleAction &action, rule.exitActions()) {
settings.beginGroup(QString::number(i));
if (!action.deviceId().isNull() && !action.actionTypeId().isNull()) {
settings.setValue("deviceId", action.deviceId().toString());
settings.setValue("actionTypeId", action.actionTypeId().toString());
saveRuleActions(&settings, rule.exitActions());
settings.endGroup();
qCDebug(dcRuleEngineDebug()) << "Saved rule to config:" << rule;
}
void RuleEngine::saveRuleActions(NymeaSettings *settings, const QList<RuleAction> &ruleActions)
{
int i = 0;
foreach (const RuleAction &action, ruleActions) {
settings->beginGroup(QString::number(i));
if (action.type() == RuleAction::TypeDevice) {
settings->setValue("deviceId", action.deviceId().toString());
settings->setValue("actionTypeId", action.actionTypeId().toString());
} else if (action.type() == RuleAction::TypeBrowser) {
settings->setValue("deviceId", action.deviceId().toString());
settings->setValue("browserItemId", action.browserItemId());
} else if (action.type() == RuleAction::TypeInterface){
settings->setValue("interface", action.interface());
settings->setValue("interfaceAction", action.interfaceAction());
} else {
settings.setValue("interface", action.interface());
settings.setValue("interfaceAction", action.interfaceAction());
Q_ASSERT_X(false, "RuleEngine::saveRule", "Unhandled rule action type.");
}
foreach (const RuleActionParam &param, action.ruleActionParams()) {
if (!param.paramTypeId().isNull()) {
settings.beginGroup("RuleActionParam-" + param.paramTypeId().toString());
settings->beginGroup("RuleActionParam-" + param.paramTypeId().toString());
} else {
settings.beginGroup("RuleActionParam-" + param.paramName());
settings->beginGroup("RuleActionParam-" + param.paramName());
}
settings.setValue("valueType", static_cast<int>(param.value().type()));
settings.setValue("value", param.value());
settings.endGroup();
settings->setValue("valueType", static_cast<int>(param.value().type()));
settings->setValue("value", param.value());
if (param.isEventBased()) {
settings->setValue("eventTypeId", param.eventTypeId().toString());
settings->setValue("eventParamTypeId", param.eventParamTypeId());
} else if (param.isStateBased()) {
settings->setValue("stateDeviceId", param.stateDeviceId().toString());
settings->setValue("stateTypeId", param.stateTypeId());
}
settings->endGroup();
}
i++;
settings.endGroup();
settings->endGroup();
}
settings.endGroup();
qCDebug(dcRuleEngineDebug()) << "Saved rule to config:" << rule;
}
void RuleEngine::init()

View File

@ -30,6 +30,7 @@
#include <QObject>
#include <QList>
#include <QUuid>
#include <QSettings>
namespace nymeaserver {
@ -112,6 +113,7 @@ private:
void appendRule(const Rule &rule);
void saveRule(const Rule &rule);
void saveRuleActions(NymeaSettings *settings, const QList<RuleAction> &ruleActions);
private:
QList<RuleId> m_ruleIds; // Keeping a list of RuleIds to keep sorting order...

View File

@ -63,8 +63,6 @@ HEADERS += \
types/paramtype.h \
types/param.h \
types/paramdescriptor.h \
types/ruleaction.h \
types/ruleactionparam.h \
types/statedescriptor.h \
types/interface.h \
hardwareresource.h \
@ -130,8 +128,6 @@ SOURCES += \
types/paramtype.cpp \
types/param.cpp \
types/paramdescriptor.cpp \
types/ruleaction.cpp \
types/ruleactionparam.cpp \
types/statedescriptor.cpp \
types/interface.cpp \
hardwareresource.cpp \