add support for interface based rules
This commit is contained in:
parent
57d4466f9a
commit
58c83e9072
2
guh.pri
2
guh.pri
@ -6,7 +6,7 @@ GUH_PLUGINS_PATH=/usr/lib/$$system('dpkg-architecture -q DEB_HOST_MULTIARCH')/gu
|
|||||||
|
|
||||||
# define protocol versions
|
# define protocol versions
|
||||||
JSON_PROTOCOL_VERSION_MAJOR=1
|
JSON_PROTOCOL_VERSION_MAJOR=1
|
||||||
JSON_PROTOCOL_VERSION_MINOR=0
|
JSON_PROTOCOL_VERSION_MINOR=1
|
||||||
REST_API_VERSION=1
|
REST_API_VERSION=1
|
||||||
|
|
||||||
DEFINES += GUH_VERSION_STRING=\\\"$${GUH_VERSION_STRING}\\\" \
|
DEFINES += GUH_VERSION_STRING=\\\"$${GUH_VERSION_STRING}\\\" \
|
||||||
|
|||||||
@ -338,9 +338,36 @@ DeviceManager::DeviceError GuhCore::executeAction(const Action &action)
|
|||||||
/*! Execute the given \a ruleActions. */
|
/*! Execute the given \a ruleActions. */
|
||||||
void GuhCore::executeRuleActions(const QList<RuleAction> ruleActions)
|
void GuhCore::executeRuleActions(const QList<RuleAction> ruleActions)
|
||||||
{
|
{
|
||||||
|
QList<Action> actions;
|
||||||
foreach (const RuleAction &ruleAction, ruleActions) {
|
foreach (const RuleAction &ruleAction, ruleActions) {
|
||||||
Action action = ruleAction.toAction();
|
if (ruleAction.type() == RuleAction::TypeDevice) {
|
||||||
qCDebug(dcRuleEngine) << "Executing action" << ruleAction.actionTypeId() << action.params();
|
actions.append(ruleAction.toAction());
|
||||||
|
} else {
|
||||||
|
QList<Device*> devices = m_deviceManager->findConfiguredDevices(ruleAction.interface());
|
||||||
|
foreach (Device* device, devices) {
|
||||||
|
DeviceClass dc = m_deviceManager->findDeviceClass(device->deviceClassId());
|
||||||
|
ActionType at = dc.actionTypes().findByName(ruleAction.interfaceAction());
|
||||||
|
if (at.id().isNull()) {
|
||||||
|
qCWarning(dcRuleEngine()) << "Error creating Action. The given DeviceClass does not implement action:" << ruleAction.interfaceAction();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Action action = Action(at.id(), device->id());
|
||||||
|
ParamList params;
|
||||||
|
foreach (const RuleActionParam &rap, ruleAction.ruleActionParams()) {
|
||||||
|
ParamType pt = at.paramTypes().findByName(rap.paramName());
|
||||||
|
if (pt.id().isNull()) {
|
||||||
|
qCWarning(dcRuleEngine()) << "Error creating Action. Failed to match interface param type to DeviceClass paramtype.";
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
params.append(Param(pt.id(), rap.value()));
|
||||||
|
}
|
||||||
|
action.setParams(params);
|
||||||
|
actions.append(action);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
foreach (const Action &action, actions) {
|
||||||
|
qCDebug(dcRuleEngine) << "Executing action" << action.actionTypeId() << action.params();
|
||||||
DeviceManager::DeviceError status = executeAction(action);
|
DeviceManager::DeviceError status = executeAction(action);
|
||||||
switch(status) {
|
switch(status) {
|
||||||
case DeviceManager::DeviceErrorNoError:
|
case DeviceManager::DeviceErrorNoError:
|
||||||
|
|||||||
@ -24,8 +24,8 @@
|
|||||||
|
|
||||||
#include "rule.h"
|
#include "rule.h"
|
||||||
#include "types/event.h"
|
#include "types/event.h"
|
||||||
|
#include "types/deviceclass.h"
|
||||||
#include "plugin/deviceplugin.h"
|
#include "plugin/deviceplugin.h"
|
||||||
#include "plugin/deviceclass.h"
|
|
||||||
#include "plugin/devicedescriptor.h"
|
#include "plugin/devicedescriptor.h"
|
||||||
|
|
||||||
#include "logging/logengine.h"
|
#include "logging/logengine.h"
|
||||||
|
|||||||
@ -57,8 +57,8 @@
|
|||||||
#include "guhcore.h"
|
#include "guhcore.h"
|
||||||
#include "devicemanager.h"
|
#include "devicemanager.h"
|
||||||
#include "loggingcategories.h"
|
#include "loggingcategories.h"
|
||||||
|
#include "types/deviceclass.h"
|
||||||
#include "plugin/device.h"
|
#include "plugin/device.h"
|
||||||
#include "plugin/deviceclass.h"
|
|
||||||
#include "plugin/deviceplugin.h"
|
#include "plugin/deviceplugin.h"
|
||||||
|
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
|||||||
@ -42,7 +42,7 @@
|
|||||||
#include "guhcore.h"
|
#include "guhcore.h"
|
||||||
#include "devicemanager.h"
|
#include "devicemanager.h"
|
||||||
#include "plugin/deviceplugin.h"
|
#include "plugin/deviceplugin.h"
|
||||||
#include "plugin/deviceclass.h"
|
#include "types/deviceclass.h"
|
||||||
#include "plugin/device.h"
|
#include "plugin/device.h"
|
||||||
#include "rule.h"
|
#include "rule.h"
|
||||||
#include "ruleengine.h"
|
#include "ruleengine.h"
|
||||||
|
|||||||
@ -22,11 +22,11 @@
|
|||||||
#ifndef JSONRPCSERVER_H
|
#ifndef JSONRPCSERVER_H
|
||||||
#define JSONRPCSERVER_H
|
#define JSONRPCSERVER_H
|
||||||
|
|
||||||
#include "plugin/deviceclass.h"
|
|
||||||
#include "jsonhandler.h"
|
#include "jsonhandler.h"
|
||||||
#include "transportinterface.h"
|
#include "transportinterface.h"
|
||||||
#include "usermanager.h"
|
#include "usermanager.h"
|
||||||
|
|
||||||
|
#include "types/deviceclass.h"
|
||||||
#include "types/action.h"
|
#include "types/action.h"
|
||||||
#include "types/event.h"
|
#include "types/event.h"
|
||||||
|
|
||||||
|
|||||||
@ -168,12 +168,15 @@ void JsonTypes::init()
|
|||||||
s_param.insert("value", basicTypeRef());
|
s_param.insert("value", basicTypeRef());
|
||||||
|
|
||||||
// RuleAction
|
// RuleAction
|
||||||
s_ruleAction.insert("actionTypeId", basicTypeToString(Uuid));
|
s_ruleAction.insert("o:deviceId", basicTypeToString(Uuid));
|
||||||
s_ruleAction.insert("deviceId", basicTypeToString(Uuid));
|
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:ruleActionParams", QVariantList() << ruleActionParamRef());
|
s_ruleAction.insert("o:ruleActionParams", QVariantList() << ruleActionParamRef());
|
||||||
|
|
||||||
// RuleActionParam
|
// RuleActionParam
|
||||||
s_ruleActionParam.insert("paramTypeId", basicTypeToString(Uuid));
|
s_ruleActionParam.insert("o:paramTypeId", basicTypeToString(Uuid));
|
||||||
|
s_ruleActionParam.insert("o:paramName", basicTypeToString(String));
|
||||||
s_ruleActionParam.insert("o:value", basicTypeRef());
|
s_ruleActionParam.insert("o:value", basicTypeRef());
|
||||||
s_ruleActionParam.insert("o:eventTypeId", basicTypeToString(Uuid));
|
s_ruleActionParam.insert("o:eventTypeId", basicTypeToString(Uuid));
|
||||||
s_ruleActionParam.insert("o:eventParamTypeId", basicTypeToString(Uuid));
|
s_ruleActionParam.insert("o:eventParamTypeId", basicTypeToString(Uuid));
|
||||||
@ -228,8 +231,10 @@ void JsonTypes::init()
|
|||||||
s_event.insert("o:params", QVariantList() << paramRef());
|
s_event.insert("o:params", QVariantList() << paramRef());
|
||||||
|
|
||||||
// EventDescriptor
|
// EventDescriptor
|
||||||
s_eventDescriptor.insert("eventTypeId", basicTypeToString(Uuid));
|
s_eventDescriptor.insert("o:eventTypeId", basicTypeToString(Uuid));
|
||||||
s_eventDescriptor.insert("deviceId", basicTypeToString(Uuid));
|
s_eventDescriptor.insert("o:deviceId", basicTypeToString(Uuid));
|
||||||
|
s_eventDescriptor.insert("o:interface", basicTypeToString(String));
|
||||||
|
s_eventDescriptor.insert("o:interfaceEvent", basicTypeToString(String));
|
||||||
s_eventDescriptor.insert("o:paramDescriptors", QVariantList() << paramDescriptorRef());
|
s_eventDescriptor.insert("o:paramDescriptors", QVariantList() << paramDescriptorRef());
|
||||||
|
|
||||||
// ActionType
|
// ActionType
|
||||||
@ -1320,10 +1325,16 @@ Rule JsonTypes::unpackRule(const QVariantMap &ruleMap)
|
|||||||
/*! Returns a \l{RuleAction} created from the given \a ruleActionMap. */
|
/*! Returns a \l{RuleAction} created from the given \a ruleActionMap. */
|
||||||
RuleAction JsonTypes::unpackRuleAction(const QVariantMap &ruleActionMap)
|
RuleAction JsonTypes::unpackRuleAction(const QVariantMap &ruleActionMap)
|
||||||
{
|
{
|
||||||
RuleAction action(ActionTypeId(ruleActionMap.value("actionTypeId").toString()), DeviceId(ruleActionMap.value("deviceId").toString()));
|
ActionTypeId actionTypeId(ruleActionMap.value("actionTypeId").toString());
|
||||||
|
DeviceId actionDeviceId(ruleActionMap.value("deviceId").toString());
|
||||||
|
QString interface = ruleActionMap.value("interface").toString();
|
||||||
|
QString interfaceAction = ruleActionMap.value("interfaceAction").toString();
|
||||||
RuleActionParamList actionParamList = JsonTypes::unpackRuleActionParams(ruleActionMap.value("ruleActionParams").toList());
|
RuleActionParamList actionParamList = JsonTypes::unpackRuleActionParams(ruleActionMap.value("ruleActionParams").toList());
|
||||||
action.setRuleActionParams(actionParamList);
|
|
||||||
return action;
|
if (!actionTypeId.isNull() && !actionDeviceId.isNull()) {
|
||||||
|
return RuleAction(actionTypeId, actionDeviceId, actionParamList);
|
||||||
|
}
|
||||||
|
return RuleAction(interface, interfaceAction, actionParamList);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Returns a \l{RuleActionParam} created from the given \a ruleActionParamMap. */
|
/*! Returns a \l{RuleActionParam} created from the given \a ruleActionParamMap. */
|
||||||
@ -1333,9 +1344,13 @@ RuleActionParam JsonTypes::unpackRuleActionParam(const QVariantMap &ruleActionPa
|
|||||||
return RuleActionParam();
|
return RuleActionParam();
|
||||||
|
|
||||||
ParamTypeId paramTypeId = ParamTypeId(ruleActionParamMap.value("paramTypeId").toString());
|
ParamTypeId paramTypeId = ParamTypeId(ruleActionParamMap.value("paramTypeId").toString());
|
||||||
|
QString paramName = ruleActionParamMap.value("paramName").toString();
|
||||||
QVariant value = ruleActionParamMap.value("value");
|
QVariant value = ruleActionParamMap.value("value");
|
||||||
EventTypeId eventTypeId = EventTypeId(ruleActionParamMap.value("eventTypeId").toString());
|
EventTypeId eventTypeId = EventTypeId(ruleActionParamMap.value("eventTypeId").toString());
|
||||||
ParamTypeId eventParamTypeId = ParamTypeId(ruleActionParamMap.value("eventParamTypeId").toString());
|
ParamTypeId eventParamTypeId = ParamTypeId(ruleActionParamMap.value("eventParamTypeId").toString());
|
||||||
|
if (paramTypeId.isNull()) {
|
||||||
|
return RuleActionParam(paramName, value, eventTypeId, eventParamTypeId);
|
||||||
|
}
|
||||||
return RuleActionParam(paramTypeId, value, eventTypeId, eventParamTypeId);
|
return RuleActionParam(paramTypeId, value, eventTypeId, eventParamTypeId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1377,9 +1392,13 @@ EventDescriptor JsonTypes::unpackEventDescriptor(const QVariantMap &eventDescrip
|
|||||||
{
|
{
|
||||||
EventTypeId eventTypeId(eventDescriptorMap.value("eventTypeId").toString());
|
EventTypeId eventTypeId(eventDescriptorMap.value("eventTypeId").toString());
|
||||||
DeviceId eventDeviceId(eventDescriptorMap.value("deviceId").toString());
|
DeviceId eventDeviceId(eventDescriptorMap.value("deviceId").toString());
|
||||||
|
QString interface = eventDescriptorMap.value("interface").toString();
|
||||||
|
QString interfaceEvent = eventDescriptorMap.value("interfaceEvent").toString();
|
||||||
QList<ParamDescriptor> eventParams = JsonTypes::unpackParamDescriptors(eventDescriptorMap.value("paramDescriptors").toList());
|
QList<ParamDescriptor> eventParams = JsonTypes::unpackParamDescriptors(eventDescriptorMap.value("paramDescriptors").toList());
|
||||||
EventDescriptor eventDescriptor(eventTypeId, eventDeviceId, eventParams);
|
if (!eventDeviceId.isNull() && !eventTypeId.isNull()) {
|
||||||
return eventDescriptor;
|
return EventDescriptor(eventTypeId, eventDeviceId, eventParams);
|
||||||
|
}
|
||||||
|
return EventDescriptor(interface, interfaceEvent, eventParams);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Returns a \l{StateEvaluator} created from the given \a stateEvaluatorMap. */
|
/*! Returns a \l{StateEvaluator} created from the given \a stateEvaluatorMap. */
|
||||||
|
|||||||
@ -23,7 +23,6 @@
|
|||||||
#ifndef JSONTYPES_H
|
#ifndef JSONTYPES_H
|
||||||
#define JSONTYPES_H
|
#define JSONTYPES_H
|
||||||
|
|
||||||
#include "plugin/deviceclass.h"
|
|
||||||
#include "plugin/devicedescriptor.h"
|
#include "plugin/devicedescriptor.h"
|
||||||
#include "rule.h"
|
#include "rule.h"
|
||||||
#include "devicemanager.h"
|
#include "devicemanager.h"
|
||||||
@ -31,6 +30,7 @@
|
|||||||
#include "guhconfiguration.h"
|
#include "guhconfiguration.h"
|
||||||
#include "usermanager.h"
|
#include "usermanager.h"
|
||||||
|
|
||||||
|
#include "types/deviceclass.h"
|
||||||
#include "types/event.h"
|
#include "types/event.h"
|
||||||
#include "types/action.h"
|
#include "types/action.h"
|
||||||
#include "types/actiontype.h"
|
#include "types/actiontype.h"
|
||||||
|
|||||||
@ -369,7 +369,7 @@ QList<Rule> RuleEngine::evaluateEvent(const Event &event)
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Event based rule
|
// Event based rule
|
||||||
if (containsEvent(rule, event) && rule.statesActive() && rule.timeActive()) {
|
if (containsEvent(rule, event, device->deviceClassId()) && rule.statesActive() && rule.timeActive()) {
|
||||||
qCDebug(dcRuleEngine) << "Rule" << rule.id() << "contains event" << event.eventId() << "and all states match.";
|
qCDebug(dcRuleEngine) << "Rule" << rule.id() << "contains event" << event.eventId() << "and all states match.";
|
||||||
rules.append(rule);
|
rules.append(rule);
|
||||||
}
|
}
|
||||||
@ -465,25 +465,42 @@ RuleEngine::RuleError RuleEngine::addRule(const Rule &rule, bool fromEdit)
|
|||||||
|
|
||||||
// Check IDs in each EventDescriptor
|
// Check IDs in each EventDescriptor
|
||||||
foreach (const EventDescriptor &eventDescriptor, rule.eventDescriptors()) {
|
foreach (const EventDescriptor &eventDescriptor, rule.eventDescriptors()) {
|
||||||
// check deviceId
|
if (!eventDescriptor.isValid()) {
|
||||||
Device *device = GuhCore::instance()->deviceManager()->findConfiguredDevice(eventDescriptor.deviceId());
|
qWarning(dcRuleEngine()) << "EventDescriptor is incomplete. It must have either eventTypeId and deviceId, or interface and interfaceEvent";
|
||||||
if (!device) {
|
|
||||||
qCWarning(dcRuleEngine) << "Cannot create rule. No configured device for eventTypeId" << eventDescriptor.eventTypeId();
|
|
||||||
return RuleErrorDeviceNotFound;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check eventTypeId for this deivce
|
|
||||||
DeviceClass deviceClass = GuhCore::instance()->deviceManager()->findDeviceClass(device->deviceClassId());
|
|
||||||
bool eventTypeFound = false;
|
|
||||||
foreach (const EventType &eventType, deviceClass.eventTypes()) {
|
|
||||||
if (eventType.id() == eventDescriptor.eventTypeId()) {
|
|
||||||
eventTypeFound = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!eventTypeFound) {
|
|
||||||
qCWarning(dcRuleEngine) << "Cannot create rule. Device " + device->name() + " has no event type:" << eventDescriptor.eventTypeId();
|
|
||||||
return RuleErrorEventTypeNotFound;
|
return RuleErrorEventTypeNotFound;
|
||||||
}
|
}
|
||||||
|
if (eventDescriptor.type() == EventDescriptor::TypeDevice) {
|
||||||
|
// check deviceId
|
||||||
|
Device *device = GuhCore::instance()->deviceManager()->findConfiguredDevice(eventDescriptor.deviceId());
|
||||||
|
if (!device) {
|
||||||
|
qCWarning(dcRuleEngine) << "Cannot create rule. No configured device for eventTypeId" << eventDescriptor.eventTypeId();
|
||||||
|
return RuleErrorDeviceNotFound;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check eventTypeId for this deivce
|
||||||
|
DeviceClass deviceClass = GuhCore::instance()->deviceManager()->findDeviceClass(device->deviceClassId());
|
||||||
|
bool eventTypeFound = false;
|
||||||
|
foreach (const EventType &eventType, deviceClass.eventTypes()) {
|
||||||
|
if (eventType.id() == eventDescriptor.eventTypeId()) {
|
||||||
|
eventTypeFound = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!eventTypeFound) {
|
||||||
|
qCWarning(dcRuleEngine) << "Cannot create rule. Device " + device->name() + " has no event type:" << eventDescriptor.eventTypeId();
|
||||||
|
return RuleErrorEventTypeNotFound;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Interface based event
|
||||||
|
Interface iface = GuhCore::instance()->deviceManager()->supportedInterfaces().findByName(eventDescriptor.interface());
|
||||||
|
if (!iface.isValid()) {
|
||||||
|
qWarning(dcRuleEngine()) << "No such interface:" << eventDescriptor.interface();
|
||||||
|
return RuleErrorInterfaceNotFound;
|
||||||
|
}
|
||||||
|
if (iface.eventTypes().findByName(eventDescriptor.interfaceEvent()).name().isEmpty()) {
|
||||||
|
qWarning(dcRuleEngine()) << "Interface" << iface.name() << "has no such event:" << eventDescriptor.interfaceEvent();
|
||||||
|
return RuleErrorEventTypeNotFound;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check state evaluator
|
// Check state evaluator
|
||||||
@ -536,104 +553,165 @@ RuleEngine::RuleError RuleEngine::addRule(const Rule &rule, bool fromEdit)
|
|||||||
|
|
||||||
// Check actions
|
// Check actions
|
||||||
foreach (const RuleAction &action, rule.actions()) {
|
foreach (const RuleAction &action, rule.actions()) {
|
||||||
Device *device = GuhCore::instance()->deviceManager()->findConfiguredDevice(action.deviceId());
|
if (!action.isValid()) {
|
||||||
if (!device) {
|
qWarning(dcRuleEngine()) << "Action is incomplete. It must have either actionTypeId and deviceId, or interface and interfaceAction";
|
||||||
qCWarning(dcRuleEngine) << "Cannot create rule. No configured device for action with actionTypeId" << action.actionTypeId();
|
|
||||||
return RuleErrorDeviceNotFound;
|
|
||||||
}
|
|
||||||
|
|
||||||
DeviceClass deviceClass = GuhCore::instance()->deviceManager()->findDeviceClass(device->deviceClassId());
|
|
||||||
if (!deviceClass.hasActionType(action.actionTypeId())) {
|
|
||||||
qCWarning(dcRuleEngine) << "Cannot create rule. Device " + device->name() + " has no action type:" << action.actionTypeId();
|
|
||||||
return RuleErrorActionTypeNotFound;
|
return RuleErrorActionTypeNotFound;
|
||||||
}
|
}
|
||||||
|
if (action.type() == RuleAction::TypeDevice) {
|
||||||
|
Device *device = GuhCore::instance()->deviceManager()->findConfiguredDevice(action.deviceId());
|
||||||
|
if (!device) {
|
||||||
|
qCWarning(dcRuleEngine) << "Cannot create rule. No configured device for action with actionTypeId" << action.actionTypeId();
|
||||||
|
return RuleErrorDeviceNotFound;
|
||||||
|
}
|
||||||
|
|
||||||
|
DeviceClass deviceClass = GuhCore::instance()->deviceManager()->findDeviceClass(device->deviceClassId());
|
||||||
|
if (!deviceClass.hasActionType(action.actionTypeId())) {
|
||||||
|
qCWarning(dcRuleEngine) << "Cannot create rule. Device " + device->name() + " has no action type:" << action.actionTypeId();
|
||||||
|
return RuleErrorActionTypeNotFound;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check possible eventTypeIds in params
|
||||||
|
if (action.isEventBased()) {
|
||||||
|
foreach (const RuleActionParam &ruleActionParam, action.ruleActionParams()) {
|
||||||
|
if (ruleActionParam.eventTypeId() != EventTypeId()) {
|
||||||
|
// We have an eventTypeId
|
||||||
|
if (rule.eventDescriptors().isEmpty()) {
|
||||||
|
qCWarning(dcRuleEngine) << "Cannot create rule. RuleAction" << action.actionTypeId() << "contains an eventTypeId, but there are no eventDescriptors.";
|
||||||
|
return RuleErrorInvalidRuleActionParameter;
|
||||||
|
}
|
||||||
|
|
||||||
|
// now check if this eventType is in the eventDescriptorList of this rule
|
||||||
|
if (!checkEventDescriptors(rule.eventDescriptors(), ruleActionParam.eventTypeId())) {
|
||||||
|
qCWarning(dcRuleEngine) << "Cannot create rule. EventTypeId from RuleAction" << action.actionTypeId() << "not in eventDescriptors.";
|
||||||
|
return RuleErrorInvalidRuleActionParameter;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if the param type of the event and the action match
|
||||||
|
QVariant::Type eventParamType = getEventParamType(ruleActionParam.eventTypeId(), ruleActionParam.eventParamTypeId());
|
||||||
|
QVariant::Type actionParamType = getActionParamType(action.actionTypeId(), ruleActionParam.paramTypeId());
|
||||||
|
if (eventParamType != actionParamType) {
|
||||||
|
qCWarning(dcRuleEngine) << "Cannot create rule. RuleActionParam" << ruleActionParam.paramTypeId().toString() << " and given event param " << ruleActionParam.eventParamTypeId().toString() << "have not the same type:";
|
||||||
|
qCWarning(dcRuleEngine) << " -> actionParamType:" << actionParamType;
|
||||||
|
qCWarning(dcRuleEngine) << " -> eventParamType:" << eventParamType;
|
||||||
|
return RuleErrorTypesNotMatching;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// verify action params
|
||||||
|
foreach (const ActionType &actionType, deviceClass.actionTypes()) {
|
||||||
|
if (actionType.id() == action.actionTypeId()) {
|
||||||
|
ParamList finalParams = action.toAction().params();
|
||||||
|
DeviceManager::DeviceError paramCheck = GuhCore::instance()->deviceManager()->verifyParams(actionType.paramTypes(), finalParams);
|
||||||
|
if (paramCheck != DeviceManager::DeviceErrorNoError) {
|
||||||
|
qCWarning(dcRuleEngine) << "Cannot create rule. Got an invalid actionParam.";
|
||||||
|
return RuleErrorInvalidRuleActionParameter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// check possible eventTypeIds in params
|
|
||||||
if (action.isEventBased()) {
|
|
||||||
foreach (const RuleActionParam &ruleActionParam, action.ruleActionParams()) {
|
foreach (const RuleActionParam &ruleActionParam, action.ruleActionParams()) {
|
||||||
if (ruleActionParam.eventTypeId() != EventTypeId()) {
|
if (!ruleActionParam.isValid()) {
|
||||||
// We have an eventTypeId
|
qCWarning(dcRuleEngine) << "Cannot create rule. Got an actionParam with \"value\" AND \"eventTypeId\".";
|
||||||
if (rule.eventDescriptors().isEmpty()) {
|
return RuleEngine::RuleErrorInvalidRuleActionParameter;
|
||||||
qCWarning(dcRuleEngine) << "Cannot create rule. RuleAction" << action.actionTypeId() << "contains an eventTypeId, but there are no eventDescriptors.";
|
|
||||||
return RuleErrorInvalidRuleActionParameter;
|
|
||||||
}
|
|
||||||
|
|
||||||
// now check if this eventType is in the eventDescriptorList of this rule
|
|
||||||
if (!checkEventDescriptors(rule.eventDescriptors(), ruleActionParam.eventTypeId())) {
|
|
||||||
qCWarning(dcRuleEngine) << "Cannot create rule. EventTypeId from RuleAction" << action.actionTypeId() << "not in eventDescriptors.";
|
|
||||||
return RuleErrorInvalidRuleActionParameter;
|
|
||||||
}
|
|
||||||
|
|
||||||
// check if the param type of the event and the action match
|
|
||||||
QVariant::Type eventParamType = getEventParamType(ruleActionParam.eventTypeId(), ruleActionParam.eventParamTypeId());
|
|
||||||
QVariant::Type actionParamType = getActionParamType(action.actionTypeId(), ruleActionParam.paramTypeId());
|
|
||||||
if (eventParamType != actionParamType) {
|
|
||||||
qCWarning(dcRuleEngine) << "Cannot create rule. RuleActionParam" << ruleActionParam.paramTypeId().toString() << " and given event param " << ruleActionParam.eventParamTypeId().toString() << "have not the same type:";
|
|
||||||
qCWarning(dcRuleEngine) << " -> actionParamType:" << actionParamType;
|
|
||||||
qCWarning(dcRuleEngine) << " -> eventParamType:" << eventParamType;
|
|
||||||
return RuleErrorTypesNotMatching;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
// verify action params
|
} else { // Is TypeInterface
|
||||||
foreach (const ActionType &actionType, deviceClass.actionTypes()) {
|
Interface iface = GuhCore::instance()->deviceManager()->supportedInterfaces().findByName(action.interface());
|
||||||
if (actionType.id() == action.actionTypeId()) {
|
if (!iface.isValid()) {
|
||||||
ParamList finalParams = action.toAction().params();
|
qCWarning(dcRuleEngine()) << "Cannot create rule. No such interface:" << action.interface();
|
||||||
DeviceManager::DeviceError paramCheck = GuhCore::instance()->deviceManager()->verifyParams(actionType.paramTypes(), finalParams);
|
return RuleError::RuleErrorInterfaceNotFound;
|
||||||
if (paramCheck != DeviceManager::DeviceErrorNoError) {
|
}
|
||||||
qCWarning(dcRuleEngine) << "Cannot create rule. Got an invalid actionParam.";
|
ActionType ifaceActionType = iface.actionTypes().findByName(action.interfaceAction());
|
||||||
return RuleErrorInvalidRuleActionParameter;
|
if (ifaceActionType.name().isEmpty()) {
|
||||||
}
|
qCWarning(dcRuleEngine()) << "Cannot create rule. Interface" << iface.name() << "does not implement action" << action.interfaceAction();
|
||||||
|
return RuleError::RuleErrorActionTypeNotFound;
|
||||||
|
}
|
||||||
|
foreach (const ParamType &ifaceActionParamType, ifaceActionType.paramTypes()) {
|
||||||
|
qWarning() << "iface requires param:" << ifaceActionParamType.name();
|
||||||
|
if (!action.ruleActionParams().hasParam(ifaceActionParamType.name())) {
|
||||||
|
qCWarning(dcRuleEngine()) << "Cannot create rule. Interface action" << iface.name() << ":" << action.interfaceAction() << "requires a" << ifaceActionParamType.name() << "param of type" << QVariant::typeToName(ifaceActionParamType.type());
|
||||||
|
return RuleError::RuleErrorMissingParameter;
|
||||||
|
}
|
||||||
|
if (!action.ruleActionParam(ifaceActionParamType.name()).value().canConvert(ifaceActionParamType.type())) {
|
||||||
|
qCWarning(dcRuleEngine()) << "Cannot create rule. Interface action parameter" << iface.name() << ":" << action.interfaceAction() << ":" << ifaceActionParamType.name() << "has wrong type. Expected" << QVariant::typeToName(ifaceActionParamType.type());
|
||||||
|
return RuleError::RuleErrorInvalidParameter;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
// TODO: Check params
|
||||||
|
|
||||||
foreach (const RuleActionParam &ruleActionParam, action.ruleActionParams()) {
|
|
||||||
if (!ruleActionParam.isValid()) {
|
|
||||||
qCWarning(dcRuleEngine) << "Cannot create rule. Got an actionParam with \"value\" AND \"eventTypeId\".";
|
|
||||||
return RuleEngine::RuleErrorInvalidRuleActionParameter;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check exit actions
|
// Check exit actions
|
||||||
foreach (const RuleAction &action, rule.exitActions()) {
|
foreach (const RuleAction &ruleAction, rule.exitActions()) {
|
||||||
Device *device = GuhCore::instance()->deviceManager()->findConfiguredDevice(action.deviceId());
|
if (!ruleAction.isValid()) {
|
||||||
if (!device) {
|
qWarning(dcRuleEngine()) << "Exit Action is incomplete. It must have either actionTypeId and deviceId, or interface and interfaceAction";
|
||||||
qCWarning(dcRuleEngine) << "Cannot create rule. No configured device for exit action with actionTypeId" << action.actionTypeId();
|
|
||||||
return RuleErrorDeviceNotFound;
|
|
||||||
}
|
|
||||||
|
|
||||||
DeviceClass deviceClass = GuhCore::instance()->deviceManager()->findDeviceClass(device->deviceClassId());
|
|
||||||
if (!deviceClass.hasActionType(action.actionTypeId())) {
|
|
||||||
qCWarning(dcRuleEngine) << "Cannot create rule. Device " + device->name() + " has no action type:" << action.actionTypeId();
|
|
||||||
return RuleErrorActionTypeNotFound;
|
return RuleErrorActionTypeNotFound;
|
||||||
}
|
}
|
||||||
|
|
||||||
// verify action params
|
if (ruleAction.type() == RuleAction::TypeDevice) {
|
||||||
foreach (const ActionType &actionType, deviceClass.actionTypes()) {
|
Device *device = GuhCore::instance()->deviceManager()->findConfiguredDevice(ruleAction.deviceId());
|
||||||
if (actionType.id() == action.actionTypeId()) {
|
if (!device) {
|
||||||
ParamList finalParams = action.toAction().params();
|
qCWarning(dcRuleEngine) << "Cannot create rule. No configured device for exit action with actionTypeId" << ruleAction.actionTypeId();
|
||||||
DeviceManager::DeviceError paramCheck = GuhCore::instance()->deviceManager()->verifyParams(actionType.paramTypes(), finalParams);
|
return RuleErrorDeviceNotFound;
|
||||||
if (paramCheck != DeviceManager::DeviceErrorNoError) {
|
}
|
||||||
qCWarning(dcRuleEngine) << "Cannot create rule. Got an invalid exit actionParam.";
|
|
||||||
return RuleErrorInvalidRuleActionParameter;
|
DeviceClass deviceClass = GuhCore::instance()->deviceManager()->findDeviceClass(device->deviceClassId());
|
||||||
|
if (!deviceClass.hasActionType(ruleAction.actionTypeId())) {
|
||||||
|
qCWarning(dcRuleEngine) << "Cannot create rule. Device " + device->name() + " has no action type:" << ruleAction.actionTypeId();
|
||||||
|
return RuleErrorActionTypeNotFound;
|
||||||
|
}
|
||||||
|
|
||||||
|
// verify action params
|
||||||
|
foreach (const ActionType &actionType, deviceClass.actionTypes()) {
|
||||||
|
if (actionType.id() == ruleAction.actionTypeId()) {
|
||||||
|
ParamList finalParams = ruleAction.toAction().params();
|
||||||
|
DeviceManager::DeviceError paramCheck = GuhCore::instance()->deviceManager()->verifyParams(actionType.paramTypes(), finalParams);
|
||||||
|
if (paramCheck != DeviceManager::DeviceErrorNoError) {
|
||||||
|
qCWarning(dcRuleEngine) << "Cannot create rule. Got an invalid exit actionParam.";
|
||||||
|
return RuleErrorInvalidRuleActionParameter;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Exit action can never be event based.
|
// Exit action can never be event based.
|
||||||
if (action.isEventBased()) {
|
if (ruleAction.isEventBased()) {
|
||||||
qCWarning(dcRuleEngine) << "Cannot create rule. Got exitAction with an actionParam containing an eventTypeId. ";
|
qCWarning(dcRuleEngine) << "Cannot create rule. Got exitAction with an actionParam containing an eventTypeId. ";
|
||||||
return RuleErrorInvalidRuleActionParameter;
|
return RuleErrorInvalidRuleActionParameter;
|
||||||
}
|
|
||||||
|
|
||||||
foreach (const RuleActionParam &ruleActionParam, action.ruleActionParams()) {
|
|
||||||
if (!ruleActionParam.isValid()) {
|
|
||||||
qCWarning(dcRuleEngine) << "Cannot create rule. Got an actionParam with \"value\" AND \"eventTypeId\".";
|
|
||||||
return RuleEngine::RuleErrorInvalidRuleActionParameter;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
foreach (const RuleActionParam &ruleActionParam, ruleAction.ruleActionParams()) {
|
||||||
|
if (!ruleActionParam.isValid()) {
|
||||||
|
qCWarning(dcRuleEngine) << "Cannot create rule. Got an actionParam with \"value\" AND \"eventTypeId\".";
|
||||||
|
return RuleEngine::RuleErrorInvalidRuleActionParameter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} else { // Is TypeInterface
|
||||||
|
Interface iface = GuhCore::instance()->deviceManager()->supportedInterfaces().findByName(ruleAction.interface());
|
||||||
|
if (!iface.isValid()) {
|
||||||
|
qCWarning(dcRuleEngine()) << "Cannot create rule. No such interface:" << ruleAction.interface();
|
||||||
|
return RuleError::RuleErrorInterfaceNotFound;
|
||||||
|
}
|
||||||
|
ActionType ifaceActionType = iface.actionTypes().findByName(ruleAction.interfaceAction());
|
||||||
|
if (ifaceActionType.name().isEmpty()) {
|
||||||
|
qCWarning(dcRuleEngine()) << "Cannot create rule. Interface" << iface.name() << "does not implement action" << ruleAction.interfaceAction();
|
||||||
|
return RuleError::RuleErrorActionTypeNotFound;
|
||||||
|
}
|
||||||
|
foreach (const ParamType &ifaceActionParamType, ifaceActionType.paramTypes()) {
|
||||||
|
qWarning() << "iface requires param:" << ifaceActionParamType.name();
|
||||||
|
if (!ruleAction.ruleActionParams().hasParam(ifaceActionParamType.name())) {
|
||||||
|
qCWarning(dcRuleEngine()) << "Cannot create rule. Interface action" << iface.name() << ":" << ruleAction.interfaceAction() << "requires a" << ifaceActionParamType.name() << "param of type" << QVariant::typeToName(ifaceActionParamType.type());
|
||||||
|
return RuleError::RuleErrorMissingParameter;
|
||||||
|
}
|
||||||
|
if (!ruleAction.ruleActionParam(ifaceActionParamType.name()).value().canConvert(ifaceActionParamType.type())) {
|
||||||
|
qCWarning(dcRuleEngine()) << "Cannot create rule. Interface action parameter" << iface.name() << ":" << ruleAction.interfaceAction() << ":" << ifaceActionParamType.name() << "has wrong type. Expected" << QVariant::typeToName(ifaceActionParamType.type());
|
||||||
|
return RuleError::RuleErrorInvalidParameter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// TODO: Check params
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -997,12 +1075,68 @@ void RuleEngine::removeDeviceFromRule(const RuleId &id, const DeviceId &deviceId
|
|||||||
emit ruleConfigurationChanged(newRule);
|
emit ruleConfigurationChanged(newRule);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RuleEngine::containsEvent(const Rule &rule, const Event &event)
|
bool RuleEngine::containsEvent(const Rule &rule, const Event &event, const DeviceClassId &deviceClassId)
|
||||||
{
|
{
|
||||||
foreach (const EventDescriptor &eventDescriptor, rule.eventDescriptors()) {
|
foreach (const EventDescriptor &eventDescriptor, rule.eventDescriptors()) {
|
||||||
if (eventDescriptor == event) {
|
// If this is a device based rule, eventTypeId and deviceId must match
|
||||||
return true;
|
if (eventDescriptor.type() == EventDescriptor::TypeDevice) {
|
||||||
|
if (eventDescriptor.eventTypeId() != event.eventTypeId() || eventDescriptor.deviceId() != event.deviceId()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If this is a interface based rule, the device must implement the interface
|
||||||
|
if (eventDescriptor.type() == EventDescriptor::TypeInterface) {
|
||||||
|
DeviceClass dc = GuhCore::instance()->deviceManager()->findDeviceClass(deviceClassId);
|
||||||
|
if (!dc.interfaces().contains(eventDescriptor.interface())) {
|
||||||
|
// DeviceClass for this event doesn't implement the interface for this eventDescriptor
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
EventType et = dc.eventTypes().findById(event.eventTypeId());
|
||||||
|
if (et.name() != eventDescriptor.interfaceEvent()) {
|
||||||
|
// The fired event name does not match with the eventDescriptor's interfaceEvent
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ok, either device/eventTypeId or interface/interfaceEvent are matching. Compare the paramdescriptor
|
||||||
|
foreach (const ParamDescriptor ¶mDescriptor, eventDescriptor.paramDescriptors()) {
|
||||||
|
switch (paramDescriptor.operatorType()) {
|
||||||
|
case Types::ValueOperatorEquals:
|
||||||
|
if (event.param(paramDescriptor.paramTypeId()).value() != paramDescriptor.value()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case Types::ValueOperatorNotEquals:
|
||||||
|
if (event.param(paramDescriptor.paramTypeId()).value() == paramDescriptor.value()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case Types::ValueOperatorGreater:
|
||||||
|
if (event.param(paramDescriptor.paramTypeId()).value() <= paramDescriptor.value()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case Types::ValueOperatorGreaterOrEqual:
|
||||||
|
if (event.param(paramDescriptor.paramTypeId()).value() < paramDescriptor.value()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case Types::ValueOperatorLess:
|
||||||
|
if (event.param(paramDescriptor.paramTypeId()).value() >= paramDescriptor.value()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case Types::ValueOperatorLessOrEqual:
|
||||||
|
if (event.param(paramDescriptor.paramTypeId()).value() < paramDescriptor.value()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// All matching!
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@ -24,7 +24,7 @@
|
|||||||
|
|
||||||
#include "rule.h"
|
#include "rule.h"
|
||||||
#include "types/event.h"
|
#include "types/event.h"
|
||||||
#include "plugin/deviceclass.h"
|
#include "types/deviceclass.h"
|
||||||
#include "stateevaluator.h"
|
#include "stateevaluator.h"
|
||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
@ -59,7 +59,8 @@ public:
|
|||||||
RuleErrorInvalidCalendarItem,
|
RuleErrorInvalidCalendarItem,
|
||||||
RuleErrorInvalidTimeEventItem,
|
RuleErrorInvalidTimeEventItem,
|
||||||
RuleErrorContainsEventBasesAction,
|
RuleErrorContainsEventBasesAction,
|
||||||
RuleErrorNoExitActions
|
RuleErrorNoExitActions,
|
||||||
|
RuleErrorInterfaceNotFound
|
||||||
};
|
};
|
||||||
|
|
||||||
enum RemovePolicy {
|
enum RemovePolicy {
|
||||||
@ -99,7 +100,7 @@ signals:
|
|||||||
void ruleConfigurationChanged(const Rule &rule);
|
void ruleConfigurationChanged(const Rule &rule);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool containsEvent(const Rule &rule, const Event &event);
|
bool containsEvent(const Rule &rule, const Event &event, const DeviceClassId &deviceClassId);
|
||||||
bool containsState(const StateEvaluator &stateEvaluator, const Event &stateChangeEvent);
|
bool containsState(const StateEvaluator &stateEvaluator, const Event &stateChangeEvent);
|
||||||
|
|
||||||
bool checkEventDescriptors(const QList<EventDescriptor> eventDescriptors, const EventTypeId &eventTypeId);
|
bool checkEventDescriptors(const QList<EventDescriptor> eventDescriptors, const EventTypeId &eventTypeId);
|
||||||
|
|||||||
@ -187,6 +187,10 @@ DeviceManager::DeviceManager(HardwareManager *hardwareManager, const QLocale &lo
|
|||||||
qRegisterMetaType<DeviceClassId>();
|
qRegisterMetaType<DeviceClassId>();
|
||||||
qRegisterMetaType<DeviceDescriptor>();
|
qRegisterMetaType<DeviceDescriptor>();
|
||||||
|
|
||||||
|
foreach (const Interface &interface, DevicePlugin::allInterfaces()) {
|
||||||
|
m_supportedInterfaces.insert(interface.name(), interface);
|
||||||
|
}
|
||||||
|
|
||||||
// Give hardware a chance to start up before loading plugins etc.
|
// Give hardware a chance to start up before loading plugins etc.
|
||||||
QMetaObject::invokeMethod(this, "loadPlugins", Qt::QueuedConnection);
|
QMetaObject::invokeMethod(this, "loadPlugins", Qt::QueuedConnection);
|
||||||
QMetaObject::invokeMethod(this, "loadConfiguredDevices", Qt::QueuedConnection);
|
QMetaObject::invokeMethod(this, "loadConfiguredDevices", Qt::QueuedConnection);
|
||||||
@ -342,6 +346,18 @@ QList<Vendor> DeviceManager::supportedVendors() const
|
|||||||
return m_supportedVendors.values();
|
return m_supportedVendors.values();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! Returns the list of all supported interfaces */
|
||||||
|
Interfaces DeviceManager::supportedInterfaces() const
|
||||||
|
{
|
||||||
|
return m_supportedInterfaces.values();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Returns the interface with the given name. If the interface can't be found it will return an invalid interface. */
|
||||||
|
Interface DeviceManager::findInterface(const QString &name)
|
||||||
|
{
|
||||||
|
return m_supportedInterfaces.value(name);
|
||||||
|
}
|
||||||
|
|
||||||
/*! Returns all the supported \l{DeviceClass}{DeviceClasses} by all \l{DevicePlugin}{DevicePlugins} loaded in the system.
|
/*! Returns all the supported \l{DeviceClass}{DeviceClasses} by all \l{DevicePlugin}{DevicePlugins} loaded in the system.
|
||||||
* Optionally filtered by \a vendorId. */
|
* Optionally filtered by \a vendorId. */
|
||||||
QList<DeviceClass> DeviceManager::supportedDevices(const VendorId &vendorId) const
|
QList<DeviceClass> DeviceManager::supportedDevices(const VendorId &vendorId) const
|
||||||
@ -769,6 +785,18 @@ QList<Device *> DeviceManager::findConfiguredDevices(const DeviceClassId &device
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QList<Device *> DeviceManager::findConfiguredDevices(const QString &interface) const
|
||||||
|
{
|
||||||
|
QList<Device*> ret;
|
||||||
|
foreach (Device *device, m_configuredDevices) {
|
||||||
|
DeviceClass dc = m_supportedDevices.value(device->deviceClassId());
|
||||||
|
if (dc.interfaces().contains(interface)) {
|
||||||
|
ret.append(device);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/*! Returns all child \l{Device}{Devices} of the given \a device. */
|
/*! Returns all child \l{Device}{Devices} of the given \a device. */
|
||||||
QList<Device *> DeviceManager::findChildDevices(const DeviceId &id) const
|
QList<Device *> DeviceManager::findChildDevices(const DeviceId &id) const
|
||||||
{
|
{
|
||||||
@ -793,7 +821,7 @@ DeviceClass DeviceManager::findDeviceClass(const DeviceClassId &deviceClassId) c
|
|||||||
return DeviceClass();
|
return DeviceClass();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Verify if the given \a params matche the given \a paramTypes. Ith \a requireAll
|
/*! Verify if the given \a params matches the given \a paramTypes. Ith \a requireAll
|
||||||
* is true, all \l{ParamList}{Params} has to be valid. Returns \l{DeviceError} to inform about the result.*/
|
* is true, all \l{ParamList}{Params} has to be valid. Returns \l{DeviceError} to inform about the result.*/
|
||||||
DeviceManager::DeviceError DeviceManager::verifyParams(const QList<ParamType> paramTypes, ParamList ¶ms, bool requireAll)
|
DeviceManager::DeviceError DeviceManager::verifyParams(const QList<ParamType> paramTypes, ParamList ¶ms, bool requireAll)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -26,10 +26,11 @@
|
|||||||
|
|
||||||
#include "libguh.h"
|
#include "libguh.h"
|
||||||
|
|
||||||
#include "plugin/deviceclass.h"
|
|
||||||
#include "plugin/device.h"
|
#include "plugin/device.h"
|
||||||
#include "plugin/devicedescriptor.h"
|
#include "plugin/devicedescriptor.h"
|
||||||
|
|
||||||
|
#include "types/deviceclass.h"
|
||||||
|
#include "types/interface.h"
|
||||||
#include "types/event.h"
|
#include "types/event.h"
|
||||||
#include "types/action.h"
|
#include "types/action.h"
|
||||||
#include "types/vendor.h"
|
#include "types/vendor.h"
|
||||||
@ -104,7 +105,10 @@ public:
|
|||||||
DeviceError setPluginConfig(const PluginId &pluginId, const ParamList &pluginConfig);
|
DeviceError setPluginConfig(const PluginId &pluginId, const ParamList &pluginConfig);
|
||||||
|
|
||||||
QList<Vendor> supportedVendors() const;
|
QList<Vendor> supportedVendors() const;
|
||||||
|
Interfaces supportedInterfaces() const;
|
||||||
|
Interface findInterface(const QString &name);
|
||||||
QList<DeviceClass> supportedDevices(const VendorId &vendorId = VendorId()) const;
|
QList<DeviceClass> supportedDevices(const VendorId &vendorId = VendorId()) const;
|
||||||
|
|
||||||
DeviceError discoverDevices(const DeviceClassId &deviceClassId, const ParamList ¶ms);
|
DeviceError discoverDevices(const DeviceClassId &deviceClassId, const ParamList ¶ms);
|
||||||
|
|
||||||
QList<Device*> configuredDevices() const;
|
QList<Device*> configuredDevices() const;
|
||||||
@ -124,6 +128,7 @@ public:
|
|||||||
|
|
||||||
Device* findConfiguredDevice(const DeviceId &id) const;
|
Device* findConfiguredDevice(const DeviceId &id) const;
|
||||||
QList<Device *> findConfiguredDevices(const DeviceClassId &deviceClassId) const;
|
QList<Device *> findConfiguredDevices(const DeviceClassId &deviceClassId) const;
|
||||||
|
QList<Device *> findConfiguredDevices(const QString &interface) const;
|
||||||
QList<Device *> findChildDevices(const DeviceId &id) const;
|
QList<Device *> findChildDevices(const DeviceId &id) const;
|
||||||
DeviceClass findDeviceClass(const DeviceClassId &deviceClassId) const;
|
DeviceClass findDeviceClass(const DeviceClassId &deviceClassId) const;
|
||||||
|
|
||||||
@ -181,6 +186,7 @@ private:
|
|||||||
|
|
||||||
QLocale m_locale;
|
QLocale m_locale;
|
||||||
QHash<VendorId, Vendor> m_supportedVendors;
|
QHash<VendorId, Vendor> m_supportedVendors;
|
||||||
|
QHash<QString, Interface> m_supportedInterfaces;
|
||||||
QHash<VendorId, QList<DeviceClassId> > m_vendorDeviceMap;
|
QHash<VendorId, QList<DeviceClassId> > m_vendorDeviceMap;
|
||||||
QHash<DeviceClassId, DeviceClass> m_supportedDevices;
|
QHash<DeviceClassId, DeviceClass> m_supportedDevices;
|
||||||
QHash<DeviceId, Device*> m_configuredDevices;
|
QHash<DeviceId, Device*> m_configuredDevices;
|
||||||
|
|||||||
14
libguh/interfaces/battery.json
Normal file
14
libguh/interfaces/battery.json
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"states": [
|
||||||
|
{
|
||||||
|
"name": "batteryLevel",
|
||||||
|
"type": "int",
|
||||||
|
"minValue": 0,
|
||||||
|
"maxValue": 100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "batteryCritical",
|
||||||
|
"type": "bool"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@ -13,5 +13,6 @@
|
|||||||
<file>extendedvolumecontroller.json</file>
|
<file>extendedvolumecontroller.json</file>
|
||||||
<file>mediametadataprovider.json</file>
|
<file>mediametadataprovider.json</file>
|
||||||
<file>mediaplayer.json</file>
|
<file>mediaplayer.json</file>
|
||||||
|
<file>battery.json</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
</RCC>
|
</RCC>
|
||||||
|
|||||||
@ -2,8 +2,8 @@
|
|||||||
"states": [
|
"states": [
|
||||||
{
|
{
|
||||||
"name": "power",
|
"name": "power",
|
||||||
"type": "bool"
|
"type": "bool",
|
||||||
|
"writable": true
|
||||||
}
|
}
|
||||||
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@ -20,7 +20,6 @@ HEADERS += devicemanager.h \
|
|||||||
loggingcategories.h \
|
loggingcategories.h \
|
||||||
guhsettings.h \
|
guhsettings.h \
|
||||||
plugin/device.h \
|
plugin/device.h \
|
||||||
plugin/deviceclass.h \
|
|
||||||
plugin/deviceplugin.h \
|
plugin/deviceplugin.h \
|
||||||
plugin/devicedescriptor.h \
|
plugin/devicedescriptor.h \
|
||||||
plugin/devicepairinginfo.h \
|
plugin/devicepairinginfo.h \
|
||||||
@ -53,6 +52,7 @@ HEADERS += devicemanager.h \
|
|||||||
coap/corelinkparser.h \
|
coap/corelinkparser.h \
|
||||||
coap/corelink.h \
|
coap/corelink.h \
|
||||||
coap/coapobserveresource.h \
|
coap/coapobserveresource.h \
|
||||||
|
types/deviceclass.h \
|
||||||
types/action.h \
|
types/action.h \
|
||||||
types/actiontype.h \
|
types/actiontype.h \
|
||||||
types/state.h \
|
types/state.h \
|
||||||
@ -67,6 +67,7 @@ HEADERS += devicemanager.h \
|
|||||||
types/ruleaction.h \
|
types/ruleaction.h \
|
||||||
types/ruleactionparam.h \
|
types/ruleactionparam.h \
|
||||||
types/statedescriptor.h \
|
types/statedescriptor.h \
|
||||||
|
types/interface.h \
|
||||||
hardwareresource.h \
|
hardwareresource.h \
|
||||||
plugintimer.h \
|
plugintimer.h \
|
||||||
hardwaremanager.h \
|
hardwaremanager.h \
|
||||||
@ -75,7 +76,6 @@ SOURCES += devicemanager.cpp \
|
|||||||
loggingcategories.cpp \
|
loggingcategories.cpp \
|
||||||
guhsettings.cpp \
|
guhsettings.cpp \
|
||||||
plugin/device.cpp \
|
plugin/device.cpp \
|
||||||
plugin/deviceclass.cpp \
|
|
||||||
plugin/deviceplugin.cpp \
|
plugin/deviceplugin.cpp \
|
||||||
plugin/devicedescriptor.cpp \
|
plugin/devicedescriptor.cpp \
|
||||||
plugin/devicepairinginfo.cpp \
|
plugin/devicepairinginfo.cpp \
|
||||||
@ -108,6 +108,7 @@ SOURCES += devicemanager.cpp \
|
|||||||
coap/corelinkparser.cpp \
|
coap/corelinkparser.cpp \
|
||||||
coap/corelink.cpp \
|
coap/corelink.cpp \
|
||||||
coap/coapobserveresource.cpp \
|
coap/coapobserveresource.cpp \
|
||||||
|
types/deviceclass.cpp \
|
||||||
types/action.cpp \
|
types/action.cpp \
|
||||||
types/actiontype.cpp \
|
types/actiontype.cpp \
|
||||||
types/state.cpp \
|
types/state.cpp \
|
||||||
@ -122,6 +123,7 @@ SOURCES += devicemanager.cpp \
|
|||||||
types/ruleaction.cpp \
|
types/ruleaction.cpp \
|
||||||
types/ruleactionparam.cpp \
|
types/ruleactionparam.cpp \
|
||||||
types/statedescriptor.cpp \
|
types/statedescriptor.cpp \
|
||||||
|
types/interface.cpp \
|
||||||
hardwareresource.cpp \
|
hardwareresource.cpp \
|
||||||
plugintimer.cpp \
|
plugintimer.cpp \
|
||||||
hardwaremanager.cpp \
|
hardwaremanager.cpp \
|
||||||
|
|||||||
@ -27,7 +27,7 @@
|
|||||||
#include "typeutils.h"
|
#include "typeutils.h"
|
||||||
#include "libguh.h"
|
#include "libguh.h"
|
||||||
|
|
||||||
#include "plugin/deviceclass.h"
|
#include "types/deviceclass.h"
|
||||||
#include "types/state.h"
|
#include "types/state.h"
|
||||||
#include "types/param.h"
|
#include "types/param.h"
|
||||||
|
|
||||||
|
|||||||
@ -797,102 +797,89 @@ void DevicePlugin::loadMetaData()
|
|||||||
|
|
||||||
QStringList interfaces;
|
QStringList interfaces;
|
||||||
foreach (const QJsonValue &value, deviceClassObject.value("interfaces").toArray()) {
|
foreach (const QJsonValue &value, deviceClassObject.value("interfaces").toArray()) {
|
||||||
QVariantMap interfaceMap = loadInterface(value.toString());
|
Interface iface = loadInterface(value.toString());
|
||||||
QVariantList states = interfaceMap.value("states").toList();
|
|
||||||
|
|
||||||
StateTypes stateTypes(deviceClass.stateTypes());
|
StateTypes stateTypes(deviceClass.stateTypes());
|
||||||
ActionTypes actionTypes(deviceClass.actionTypes());
|
ActionTypes actionTypes(deviceClass.actionTypes());
|
||||||
EventTypes eventTypes(deviceClass.eventTypes());
|
EventTypes eventTypes(deviceClass.eventTypes());
|
||||||
bool valid = true;
|
bool valid = true;
|
||||||
foreach (const QVariant &stateVariant, states) {
|
foreach (const StateType &ifaceStateType, iface.stateTypes()) {
|
||||||
StateType stateType = stateTypes.findByName(stateVariant.toMap().value("name").toString());
|
StateType stateType = stateTypes.findByName(ifaceStateType.name());
|
||||||
QVariantMap stateMap = stateVariant.toMap();
|
|
||||||
if (stateType.id().isNull()) {
|
if (stateType.id().isNull()) {
|
||||||
qCWarning(dcDeviceManager) << "DeviceClass" << deviceClass.name() << "claims to implement interface" << value.toString() << "but doesn't implement state" << stateMap.value("name").toString();
|
qCWarning(dcDeviceManager) << "DeviceClass" << deviceClass.name() << "claims to implement interface" << value.toString() << "but doesn't implement state" << ifaceStateType.name();
|
||||||
valid = false;
|
valid = false;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (QVariant::nameToType(stateMap.value("type").toByteArray().data()) != stateType.type()) {
|
if (ifaceStateType.type() != stateType.type()) {
|
||||||
qCWarning(dcDeviceManager) << "DeviceClass" << deviceClass.name() << "claims to implement interface" << value.toString() << "but state" << stateMap.value("name").toString() << "has not matching type" << stateMap.value("type").toString();
|
qCWarning(dcDeviceManager) << "DeviceClass" << deviceClass.name() << "claims to implement interface" << value.toString() << "but state" << stateType.name() << "has not matching type" << stateType.type() << "!=" << ifaceStateType.type();
|
||||||
valid = false;
|
valid = false;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (stateMap.contains("minimumValue")) {
|
if (ifaceStateType.minValue().isValid() && !ifaceStateType.minValue().isNull()) {
|
||||||
if (stateMap.value("minimumValue").toString() == "any") {
|
if (ifaceStateType.minValue().toString() == "any") {
|
||||||
if (stateType.minValue().isNull()) {
|
if (stateType.minValue().isNull()) {
|
||||||
qCWarning(dcDeviceManager) << "DeviceClass" << deviceClass.name() << "claims to implement interface" << value.toString() << "but state" << stateMap.value("name").toString() << "has no minimum value defined.";
|
qCWarning(dcDeviceManager) << "DeviceClass" << deviceClass.name() << "claims to implement interface" << value.toString() << "but state" << stateType.name() << "has no minimum value defined.";
|
||||||
valid = false;
|
valid = false;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
} else if (stateMap.value("minimumValue") != stateType.minValue()) {
|
} else if (ifaceStateType.minValue() != stateType.minValue()) {
|
||||||
qCWarning(dcDeviceManager) << "DeviceClass" << deviceClass.name() << "claims to implement interface" << value.toString() << "but state" << stateMap.value("name").toString() << "has not matching minimum value:" << stateMap.value("minimumValue") << "!=" << stateType.minValue();
|
qCWarning(dcDeviceManager) << "DeviceClass" << deviceClass.name() << "claims to implement interface" << value.toString() << "but state" << stateType.name() << "has not matching minimum value:" << ifaceStateType.minValue() << "!=" << stateType.minValue();
|
||||||
valid = false;
|
valid = false;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (stateMap.contains("maximumValue")) {
|
if (ifaceStateType.maxValue().isValid() && !ifaceStateType.maxValue().isNull()) {
|
||||||
if (stateMap.value("maximumValue").toString() == "any") {
|
if (ifaceStateType.maxValue().toString() == "any") {
|
||||||
if (stateType.maxValue().isNull()) {
|
if (stateType.maxValue().isNull()) {
|
||||||
qCWarning(dcDeviceManager) << "DeviceClass" << deviceClass.name() << "claims to implement interface" << value.toString() << "but state" << stateMap.value("name").toString() << "has no maximum value defined.";
|
qCWarning(dcDeviceManager) << "DeviceClass" << deviceClass.name() << "claims to implement interface" << value.toString() << "but state" << stateType.name() << "has no maximum value defined.";
|
||||||
valid = false;
|
valid = false;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
} else if (stateMap.value("maximumValue") != stateType.maxValue()) {
|
} else if (ifaceStateType.maxValue() != stateType.maxValue()) {
|
||||||
qCWarning(dcDeviceManager) << "DeviceClass" << deviceClass.name() << "claims to implement interface" << value.toString() << "but state" << stateMap.value("name").toString() << "has not matching maximum value:" << stateMap.value("maximumValue") << "!=" << stateType.minValue();
|
qCWarning(dcDeviceManager) << "DeviceClass" << deviceClass.name() << "claims to implement interface" << value.toString() << "but state" << stateType.name() << "has not matching maximum value:" << ifaceStateType.maxValue() << "!=" << stateType.minValue();
|
||||||
valid = false;
|
valid = false;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (stateMap.contains("allowedValues") && stateMap.value("allowedValues") != stateType.possibleValues()) {
|
if (!ifaceStateType.possibleValues().isEmpty() && ifaceStateType.possibleValues() != stateType.possibleValues()) {
|
||||||
qCWarning(dcDeviceManager) << "DeviceClass" << deviceClass.name() << "claims to implement interface" << value.toString() << "but state" << stateMap.value("name").toString() << "has not matching allowed values" << stateMap.value("allowedValues") << "!=" << stateType.possibleValues();
|
qCWarning(dcDeviceManager) << "DeviceClass" << deviceClass.name() << "claims to implement interface" << value.toString() << "but state" << stateType.name() << "has not matching allowed values" << ifaceStateType.possibleValues() << "!=" << stateType.possibleValues();
|
||||||
valid = false;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (stateMap.contains("writable") && stateMap.value("writable").toBool() && actionTypes.findById(ActionTypeId(stateType.id().toString())).id().isNull()) {
|
|
||||||
qCWarning(dcDeviceManager) << "DeviceClass" << deviceClass.name() << "claims to implement interface" << value.toString() << "but state" << stateMap.value("name").toString() << "is not writable while it should be";
|
|
||||||
valid = false;
|
valid = false;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
QVariantList actions = interfaceMap.value("actions").toList();
|
foreach (const ActionType &ifaceActionType, iface.actionTypes()) {
|
||||||
foreach (const QVariant &actionVariant, actions) {
|
ActionType actionType = actionTypes.findByName(ifaceActionType.name());
|
||||||
QVariantMap actionMap = actionVariant.toMap();
|
|
||||||
ActionType actionType = actionTypes.findByName(actionMap.value("name").toString());
|
|
||||||
if (actionType.id().isNull()) {
|
if (actionType.id().isNull()) {
|
||||||
qCWarning(dcDeviceManager) << "DeviceClass" << deviceClass.name() << "claims to implement interface" << value.toString() << "but doesn't implement action" << actionMap.value("name").toString();
|
qCWarning(dcDeviceManager) << "DeviceClass" << deviceClass.name() << "claims to implement interface" << value.toString() << "but doesn't implement action" << ifaceActionType.name();
|
||||||
valid = false;
|
valid = false;
|
||||||
}
|
}
|
||||||
QVariantList params = actionMap.value("params").toList();
|
foreach (const ParamType &ifaceActionParamType, ifaceActionType.paramTypes()) {
|
||||||
foreach (const QVariant ¶mVariant, params) {
|
ParamType paramType = actionType.paramTypes().findByName(ifaceActionParamType.name());
|
||||||
ParamType paramType = actionType.paramTypes().findByName(paramVariant.toMap().value("name").toString());
|
|
||||||
if (!paramType.isValid()) {
|
if (!paramType.isValid()) {
|
||||||
qCWarning(dcDeviceManager) << "DeviceClass" << deviceClass.name() << "claims to implement interface" << value.toString() << "but doesn't implement action param" << actionMap.value("name").toString() << ":" << paramVariant.toMap().value("name").toString();
|
qCWarning(dcDeviceManager) << "DeviceClass" << deviceClass.name() << "claims to implement interface" << value.toString() << "but doesn't implement action param" << ifaceActionType.name() << ":" << ifaceActionParamType.name();
|
||||||
valid = false;
|
valid = false;
|
||||||
} else {
|
} else {
|
||||||
if (paramType.type() != QVariant::nameToType(paramVariant.toMap().value("type").toString().toLatin1())) {
|
if (paramType.type() != ifaceActionParamType.type()) {
|
||||||
qCWarning(dcDeviceManager()) << "DeviceClass" << deviceClass.name() << "claims to implement interface" << value.toString() << "but param" << paramType.name() << "is of wrong type:" << QVariant::typeToName(paramType.type()) << "expected:" << paramVariant.toMap().value("type").toString();
|
qCWarning(dcDeviceManager()) << "DeviceClass" << deviceClass.name() << "claims to implement interface" << value.toString() << "but param" << paramType.name() << "is of wrong type:" << QVariant::typeToName(paramType.type()) << "expected:" << QVariant::typeToName(ifaceActionParamType.type());
|
||||||
valid = false;
|
valid = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
QVariantList events = interfaceMap.value("events").toList();
|
foreach (const EventType &ifaceEventType, iface.eventTypes()) {
|
||||||
foreach (const QVariant &eventVariant, events) {
|
EventType eventType = eventTypes.findByName(ifaceEventType.name());
|
||||||
QVariantMap eventMap = eventVariant.toMap();
|
if (!eventType.isValid()) {
|
||||||
EventType eventType = eventTypes.findByName(eventMap.value("name").toString());
|
qCWarning(dcDeviceManager) << "DeviceClass" << deviceClass.name() << "claims to implement interface" << value.toString() << "but doesn't implement event" << ifaceEventType.name();
|
||||||
if (eventType.isValid()) {
|
|
||||||
qCWarning(dcDeviceManager) << "DeviceClass" << deviceClass.name() << "claims to implement interface" << value.toString() << "but doesn't implement event" << eventMap.value("name").toString();
|
|
||||||
valid = false;
|
valid = false;
|
||||||
}
|
}
|
||||||
QVariantList params = eventMap.value("params").toList();
|
foreach (const ParamType &ifaceEventParamType, ifaceEventType.paramTypes()) {
|
||||||
foreach (const QVariant ¶mVariant, params) {
|
ParamType paramType = eventType.paramTypes().findByName(ifaceEventParamType.name());
|
||||||
ParamType paramType = eventType.paramTypes().findByName(paramVariant.toMap().value("name").toString());
|
|
||||||
if (!paramType.isValid()) {
|
if (!paramType.isValid()) {
|
||||||
qCWarning(dcDeviceManager) << "DeviceClass" << deviceClass.name() << "claims to implement interface" << value.toString() << "but doesn't implement action param" << eventMap.value("name").toString() << ":" << paramVariant.toMap().value("name").toString();
|
qCWarning(dcDeviceManager) << "DeviceClass" << deviceClass.name() << "claims to implement interface" << value.toString() << "but doesn't implement event param" << ifaceEventType.name() << ":" << ifaceEventParamType.name();
|
||||||
valid = false;
|
valid = false;
|
||||||
} else {
|
} else {
|
||||||
if (paramType.type() != QVariant::nameToType(paramVariant.toMap().value("type").toString().toLatin1())) {
|
if (paramType.type() != ifaceEventParamType.type()) {
|
||||||
qCWarning(dcDeviceManager()) << "DeviceClass" << deviceClass.name() << "claims to implement interface" << value.toString() << "but param" << paramType.name() << "is of wrong type:" << QVariant::typeToName(paramType.type()) << "expected:" << paramVariant.toMap().value("type").toString();
|
qCWarning(dcDeviceManager()) << "DeviceClass" << deviceClass.name() << "claims to implement interface" << value.toString() << "but param" << paramType.name() << "is of wrong type:" << QVariant::typeToName(paramType.type()) << "expected:" << QVariant::typeToName(ifaceEventParamType.type());
|
||||||
valid = false;
|
valid = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1038,36 +1025,100 @@ QPair<bool, DeviceClass::DeviceIcon> DevicePlugin::loadAndVerifyDeviceIcon(const
|
|||||||
return QPair<bool, DeviceClass::DeviceIcon>(true, (DeviceClass::DeviceIcon)enumValue);
|
return QPair<bool, DeviceClass::DeviceIcon>(true, (DeviceClass::DeviceIcon)enumValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
QVariantMap DevicePlugin::loadInterface(const QString &name)
|
Interfaces DevicePlugin::allInterfaces()
|
||||||
{
|
{
|
||||||
|
Interfaces ret;
|
||||||
|
QDir dir(":/interfaces/");
|
||||||
|
foreach (const QFileInfo &ifaceFile, dir.entryInfoList()) {
|
||||||
|
ret.append(loadInterface(ifaceFile.baseName()));
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
Interface DevicePlugin::loadInterface(const QString &name)
|
||||||
|
{
|
||||||
|
Interface iface;
|
||||||
QFile f(QString(":/interfaces/%1.json").arg(name));
|
QFile f(QString(":/interfaces/%1.json").arg(name));
|
||||||
if (!f.open(QFile::ReadOnly)) {
|
if (!f.open(QFile::ReadOnly)) {
|
||||||
qCWarning(dcDeviceManager()) << "Failed to load interface" << name;
|
qCWarning(dcDeviceManager()) << "Failed to load interface" << name;
|
||||||
return QVariantMap();
|
return iface;
|
||||||
}
|
}
|
||||||
QJsonParseError error;
|
QJsonParseError error;
|
||||||
QJsonDocument jsonDoc = QJsonDocument::fromJson(f.readAll(), &error);
|
QJsonDocument jsonDoc = QJsonDocument::fromJson(f.readAll(), &error);
|
||||||
if (error.error != QJsonParseError::NoError) {
|
if (error.error != QJsonParseError::NoError) {
|
||||||
qCWarning(dcDeviceManager) << "Cannot load interface definition for interface" << name << ":" << error.errorString();
|
qCWarning(dcDeviceManager) << "Cannot load interface definition for interface" << name << ":" << error.errorString();
|
||||||
return QVariantMap();
|
return iface;
|
||||||
}
|
}
|
||||||
QVariantMap content = jsonDoc.toVariant().toMap();
|
QVariantMap content = jsonDoc.toVariant().toMap();
|
||||||
if (content.contains("extends")) {
|
if (content.contains("extends")) {
|
||||||
QVariantMap parentContent = loadInterface(content.value("extends").toString());
|
iface = loadInterface(content.value("extends").toString());
|
||||||
|
|
||||||
QVariantList statesList = content.value("states").toList();
|
|
||||||
statesList.append(parentContent.value("states").toList());
|
|
||||||
content["states"] = statesList;
|
|
||||||
|
|
||||||
QVariantList actionsList = content.value("actions").toList();
|
|
||||||
actionsList.append(parentContent.value("actions").toList());
|
|
||||||
content["actions"] = actionsList;
|
|
||||||
|
|
||||||
QVariantList eventsList = content.value("events").toList();
|
|
||||||
eventsList.append(parentContent.value("events").toList());
|
|
||||||
content["events"] = eventsList;
|
|
||||||
}
|
}
|
||||||
return content;
|
|
||||||
|
StateTypes stateTypes;
|
||||||
|
ActionTypes actionTypes;
|
||||||
|
EventTypes eventTypes;
|
||||||
|
foreach (const QVariant &stateVariant, content.value("states").toList()) {
|
||||||
|
StateType stateType(StateTypeId::fromUuid(QUuid()));
|
||||||
|
stateType.setName(stateVariant.toMap().value("name").toString());
|
||||||
|
stateType.setType(QVariant::nameToType(stateVariant.toMap().value("type").toByteArray()));
|
||||||
|
stateType.setPossibleValues(stateVariant.toMap().value("allowedValues").toList());
|
||||||
|
stateType.setMinValue(stateVariant.toMap().value("minValue"));
|
||||||
|
stateType.setMaxValue(stateVariant.toMap().value("maxValue"));
|
||||||
|
stateTypes.append(stateType);
|
||||||
|
|
||||||
|
EventType stateChangeEventType(EventTypeId::fromUuid(QUuid()));
|
||||||
|
stateChangeEventType.setName(stateType.name());
|
||||||
|
ParamType stateChangeEventParamType;
|
||||||
|
stateChangeEventParamType.setName(stateType.name());
|
||||||
|
stateChangeEventParamType.setType(stateType.type());
|
||||||
|
stateChangeEventParamType.setAllowedValues(stateType.possibleValues());
|
||||||
|
stateChangeEventParamType.setMinValue(stateType.minValue());
|
||||||
|
stateChangeEventParamType.setMaxValue(stateType.maxValue());
|
||||||
|
stateChangeEventType.setParamTypes(ParamTypes() << stateChangeEventParamType);
|
||||||
|
eventTypes.append(stateChangeEventType);
|
||||||
|
|
||||||
|
if (stateVariant.toMap().value("writable", false).toBool()) {
|
||||||
|
ActionType stateChangeActionType(ActionTypeId::fromUuid(QUuid()));
|
||||||
|
stateChangeActionType.setName(stateType.name());
|
||||||
|
stateChangeActionType.setParamTypes(ParamTypes() << stateChangeEventParamType);
|
||||||
|
actionTypes.append(stateChangeActionType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (const QVariant &actionVariant, content.value("actions").toList()) {
|
||||||
|
ActionType actionType(ActionTypeId::fromUuid(QUuid()));
|
||||||
|
actionType.setName(actionVariant.toMap().value("name").toString());
|
||||||
|
ParamTypes paramTypes;
|
||||||
|
foreach (const QVariant &actionParamVariant, actionVariant.toMap().value("params").toList()) {
|
||||||
|
ParamType paramType;
|
||||||
|
paramType.setName(actionParamVariant.toMap().value("name").toString());
|
||||||
|
paramType.setType(QVariant::nameToType(actionParamVariant.toMap().value("type").toByteArray()));
|
||||||
|
paramType.setAllowedValues(actionParamVariant.toMap().value("allowedValues").toList());
|
||||||
|
paramType.setMinValue(actionParamVariant.toMap().value("min"));
|
||||||
|
paramTypes.append(paramType);
|
||||||
|
}
|
||||||
|
actionType.setParamTypes(paramTypes);
|
||||||
|
actionTypes.append(actionType);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (const QVariant &eventVariant, content.value("events").toList()) {
|
||||||
|
EventType eventType(EventTypeId::fromUuid(QUuid()));
|
||||||
|
eventType.setName(eventVariant.toMap().value("name").toString());
|
||||||
|
ParamTypes paramTypes;
|
||||||
|
foreach (const QVariant &eventParamVariant, eventVariant.toMap().value("params").toList()) {
|
||||||
|
ParamType paramType;
|
||||||
|
paramType.setName(eventParamVariant.toMap().value("name").toString());
|
||||||
|
paramType.setType(QVariant::nameToType(eventParamVariant.toMap().value("type").toByteArray()));
|
||||||
|
paramType.setAllowedValues(eventParamVariant.toMap().value("allowedValues").toList());
|
||||||
|
paramType.setMinValue(eventParamVariant.toMap().value("minValue"));
|
||||||
|
paramType.setMaxValue(eventParamVariant.toMap().value("maxValue"));
|
||||||
|
paramTypes.append(paramType);
|
||||||
|
}
|
||||||
|
eventType.setParamTypes(paramTypes);
|
||||||
|
eventTypes.append(eventType);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Interface(name, iface.actionTypes() << actionTypes, iface.eventTypes() << eventTypes, iface.stateTypes() << stateTypes);
|
||||||
}
|
}
|
||||||
|
|
||||||
QStringList DevicePlugin::generateInterfaceParentList(const QString &interface)
|
QStringList DevicePlugin::generateInterfaceParentList(const QString &interface)
|
||||||
|
|||||||
@ -25,11 +25,11 @@
|
|||||||
#define DEVICEPLUGIN_H
|
#define DEVICEPLUGIN_H
|
||||||
|
|
||||||
#include "devicemanager.h"
|
#include "devicemanager.h"
|
||||||
#include "deviceclass.h"
|
|
||||||
|
|
||||||
#include "libguh.h"
|
#include "libguh.h"
|
||||||
#include "typeutils.h"
|
#include "typeutils.h"
|
||||||
|
|
||||||
|
#include "types/deviceclass.h"
|
||||||
#include "types/event.h"
|
#include "types/event.h"
|
||||||
#include "types/action.h"
|
#include "types/action.h"
|
||||||
#include "types/vendor.h"
|
#include "types/vendor.h"
|
||||||
@ -119,7 +119,11 @@ private:
|
|||||||
QPair<bool, DeviceClass::BasicTag> loadAndVerifyBasicTag(const QString &basicTag) const;
|
QPair<bool, DeviceClass::BasicTag> loadAndVerifyBasicTag(const QString &basicTag) const;
|
||||||
QPair<bool, DeviceClass::DeviceIcon> loadAndVerifyDeviceIcon(const QString &deviceIcon) const;
|
QPair<bool, DeviceClass::DeviceIcon> loadAndVerifyDeviceIcon(const QString &deviceIcon) const;
|
||||||
|
|
||||||
static QVariantMap loadInterface(const QString &name);
|
// FIXME: This is expensive because it will open all the files.
|
||||||
|
// Once DeviceManager is in libguh-core this should probably be there too.
|
||||||
|
// I didn't want to add even more dependencies on the devicemanager into here, so reading the list here for now.
|
||||||
|
static Interfaces allInterfaces();
|
||||||
|
static Interface loadInterface(const QString &name);
|
||||||
static QStringList generateInterfaceParentList(const QString &interface);
|
static QStringList generateInterfaceParentList(const QString &interface);
|
||||||
|
|
||||||
QTranslator *m_translator = nullptr;
|
QTranslator *m_translator = nullptr;
|
||||||
|
|||||||
@ -60,6 +60,7 @@ private:
|
|||||||
class ActionTypes: public QList<ActionType>
|
class ActionTypes: public QList<ActionType>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
ActionTypes() = default;
|
||||||
ActionTypes(const QList<ActionType> &other);
|
ActionTypes(const QList<ActionType> &other);
|
||||||
ActionType findByName(const QString &name);
|
ActionType findByName(const QString &name);
|
||||||
ActionType findById(const ActionTypeId &id);
|
ActionType findById(const ActionTypeId &id);
|
||||||
|
|||||||
@ -336,7 +336,7 @@ bool DeviceClass::hasStateType(const StateTypeId &stateTypeId)
|
|||||||
|
|
||||||
/*! Returns the eventTypes of this DeviceClass. \{Device}{Devices} created
|
/*! Returns the eventTypes of this DeviceClass. \{Device}{Devices} created
|
||||||
from this \l{DeviceClass} must have their events matching to this template. */
|
from this \l{DeviceClass} must have their events matching to this template. */
|
||||||
QList<EventType> DeviceClass::eventTypes() const
|
EventTypes DeviceClass::eventTypes() const
|
||||||
{
|
{
|
||||||
return m_eventTypes;
|
return m_eventTypes;
|
||||||
}
|
}
|
||||||
@ -361,7 +361,7 @@ bool DeviceClass::hasEventType(const EventTypeId &eventTypeId)
|
|||||||
|
|
||||||
/*! Returns the actionTypes of this DeviceClass. \{Device}{Devices} created
|
/*! Returns the actionTypes of this DeviceClass. \{Device}{Devices} created
|
||||||
from this \l{DeviceClass} must have their actions matching to this template. */
|
from this \l{DeviceClass} must have their actions matching to this template. */
|
||||||
QList<ActionType> DeviceClass::actionTypes() const
|
ActionTypes DeviceClass::actionTypes() const
|
||||||
{
|
{
|
||||||
return m_actionTypes;
|
return m_actionTypes;
|
||||||
}
|
}
|
||||||
@ -152,11 +152,11 @@ public:
|
|||||||
void setStateTypes(const QList<StateType> &stateTypes);
|
void setStateTypes(const QList<StateType> &stateTypes);
|
||||||
bool hasStateType(const StateTypeId &stateTypeId);
|
bool hasStateType(const StateTypeId &stateTypeId);
|
||||||
|
|
||||||
QList<EventType> eventTypes() const;
|
EventTypes eventTypes() const;
|
||||||
void setEventTypes(const QList<EventType> &eventTypes);
|
void setEventTypes(const QList<EventType> &eventTypes);
|
||||||
bool hasEventType(const EventTypeId &eventTypeId);
|
bool hasEventType(const EventTypeId &eventTypeId);
|
||||||
|
|
||||||
QList<ActionType> actionTypes() const;
|
ActionTypes actionTypes() const;
|
||||||
void setActionTypes(const QList<ActionType> &actionTypes);
|
void setActionTypes(const QList<ActionType> &actionTypes);
|
||||||
bool hasActionType(const ActionTypeId &actionTypeId);
|
bool hasActionType(const ActionTypeId &actionTypeId);
|
||||||
|
|
||||||
@ -31,6 +31,11 @@
|
|||||||
|
|
||||||
An EventDescriptor describes an \l{Event} in order to match it with a \l{guhserver::Rule}.
|
An EventDescriptor describes an \l{Event} in order to match it with a \l{guhserver::Rule}.
|
||||||
|
|
||||||
|
An EventDescriptor can either be bound to a certain device/eventtype, or to an interface.
|
||||||
|
If an event is bound to a device, it will only match when the given device fires the given event.
|
||||||
|
If an event is bound to an interface, it will match the given event for all the devices implementing
|
||||||
|
the given interface.
|
||||||
|
|
||||||
\sa Event, EventType, guhserver::Rule
|
\sa Event, EventType, guhserver::Rule
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -44,6 +49,25 @@ EventDescriptor::EventDescriptor(const EventTypeId &eventTypeId, const DeviceId
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EventDescriptor::EventDescriptor(const QString &interface, const QString &interfaceEvent, const QList<ParamDescriptor> ¶mDescriptors):
|
||||||
|
m_interface(interface),
|
||||||
|
m_interfaceEvent(interfaceEvent),
|
||||||
|
m_paramDescriptors(paramDescriptors)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
EventDescriptor::Type EventDescriptor::type() const
|
||||||
|
{
|
||||||
|
return (!m_deviceId.isNull() && !m_eventTypeId.isNull()) ? TypeDevice : TypeInterface;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Returns true if the EventDescriptor is valid, that is, when it has either enough data to describe a device/eventType or an interface/interfaceEvent pair. */
|
||||||
|
bool EventDescriptor::isValid() const
|
||||||
|
{
|
||||||
|
return (!m_deviceId.isNull() && !m_eventTypeId.isNull()) || (!m_interface.isEmpty() && !m_interfaceEvent.isEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
/*! Returns the id of the \l{EventType} which describes this Event. */
|
/*! Returns the id of the \l{EventType} which describes this Event. */
|
||||||
EventTypeId EventDescriptor::eventTypeId() const
|
EventTypeId EventDescriptor::eventTypeId() const
|
||||||
{
|
{
|
||||||
@ -56,6 +80,18 @@ DeviceId EventDescriptor::deviceId() const
|
|||||||
return m_deviceId;
|
return m_deviceId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! Returns the interface associated with this EventDescriptor. */
|
||||||
|
QString EventDescriptor::interface() const
|
||||||
|
{
|
||||||
|
return m_interface;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Returns the interface's event name associated with this EventDescriptor.*/
|
||||||
|
QString EventDescriptor::interfaceEvent() const
|
||||||
|
{
|
||||||
|
return m_interfaceEvent;
|
||||||
|
}
|
||||||
|
|
||||||
/*! Returns the parameters of this Event. */
|
/*! Returns the parameters of this Event. */
|
||||||
QList<ParamDescriptor> EventDescriptor::paramDescriptors() const
|
QList<ParamDescriptor> EventDescriptor::paramDescriptors() const
|
||||||
{
|
{
|
||||||
@ -97,51 +133,6 @@ bool EventDescriptor::operator ==(const EventDescriptor &other) const
|
|||||||
&& paramsMatch;
|
&& paramsMatch;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Compare this EventDescriptor to the Event given by \a event.
|
|
||||||
* Events are equal (returns true) if eventTypeId, deviceId and params match. */
|
|
||||||
bool EventDescriptor::operator ==(const Event &event) const
|
|
||||||
{
|
|
||||||
if (m_eventTypeId != event.eventTypeId() || m_deviceId != event.deviceId()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (const ParamDescriptor ¶mDescriptor, m_paramDescriptors) {
|
|
||||||
switch (paramDescriptor.operatorType()) {
|
|
||||||
case Types::ValueOperatorEquals:
|
|
||||||
if (event.param(paramDescriptor.paramTypeId()).value() != paramDescriptor.value()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case Types::ValueOperatorNotEquals:
|
|
||||||
if (event.param(paramDescriptor.paramTypeId()).value() == paramDescriptor.value()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case Types::ValueOperatorGreater:
|
|
||||||
if (event.param(paramDescriptor.paramTypeId()).value() <= paramDescriptor.value()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case Types::ValueOperatorGreaterOrEqual:
|
|
||||||
if (event.param(paramDescriptor.paramTypeId()).value() < paramDescriptor.value()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case Types::ValueOperatorLess:
|
|
||||||
if (event.param(paramDescriptor.paramTypeId()).value() >= paramDescriptor.value()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case Types::ValueOperatorLessOrEqual:
|
|
||||||
if (event.param(paramDescriptor.paramTypeId()).value() < paramDescriptor.value()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! Writes the eventTypeId and the deviceId of the given \a eventDescriptor to \a dbg. */
|
/*! Writes the eventTypeId and the deviceId of the given \a eventDescriptor to \a dbg. */
|
||||||
QDebug operator<<(QDebug dbg, const EventDescriptor &eventDescriptor)
|
QDebug operator<<(QDebug dbg, const EventDescriptor &eventDescriptor)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -36,22 +36,34 @@
|
|||||||
class LIBGUH_EXPORT EventDescriptor
|
class LIBGUH_EXPORT EventDescriptor
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
enum Type {
|
||||||
|
TypeDevice,
|
||||||
|
TypeInterface
|
||||||
|
};
|
||||||
|
|
||||||
EventDescriptor(const EventTypeId &eventTypeId, const DeviceId &deviceId, const QList<ParamDescriptor> ¶mDescriptors = QList<ParamDescriptor>());
|
EventDescriptor(const EventTypeId &eventTypeId, const DeviceId &deviceId, const QList<ParamDescriptor> ¶mDescriptors = QList<ParamDescriptor>());
|
||||||
|
EventDescriptor(const QString &interface, const QString &interfaceEvent, const QList<ParamDescriptor> ¶mDescriptors = QList<ParamDescriptor>());
|
||||||
|
|
||||||
|
Type type() const;
|
||||||
|
bool isValid() const;
|
||||||
|
|
||||||
EventTypeId eventTypeId() const;
|
EventTypeId eventTypeId() const;
|
||||||
DeviceId deviceId() const;
|
DeviceId deviceId() const;
|
||||||
|
|
||||||
|
QString interface() const;
|
||||||
|
QString interfaceEvent() const;
|
||||||
|
|
||||||
QList<ParamDescriptor> paramDescriptors() const;
|
QList<ParamDescriptor> paramDescriptors() const;
|
||||||
void setParamDescriptors(const QList<ParamDescriptor> ¶mDescriptors);
|
void setParamDescriptors(const QList<ParamDescriptor> ¶mDescriptors);
|
||||||
ParamDescriptor paramDescriptor(const ParamTypeId ¶mTypeId) const;
|
ParamDescriptor paramDescriptor(const ParamTypeId ¶mTypeId) const;
|
||||||
|
|
||||||
bool operator ==(const EventDescriptor &other) const;
|
bool operator ==(const EventDescriptor &other) const;
|
||||||
|
|
||||||
bool operator ==(const Event &event) const;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
EventTypeId m_eventTypeId;
|
EventTypeId m_eventTypeId;
|
||||||
DeviceId m_deviceId;
|
DeviceId m_deviceId;
|
||||||
|
QString m_interface;
|
||||||
|
QString m_interfaceEvent;
|
||||||
QList<ParamDescriptor> m_paramDescriptors;
|
QList<ParamDescriptor> m_paramDescriptors;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -69,6 +69,7 @@ private:
|
|||||||
class EventTypes: public QList<EventType>
|
class EventTypes: public QList<EventType>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
EventTypes() = default;
|
||||||
EventTypes(const QList<EventType> &other);
|
EventTypes(const QList<EventType> &other);
|
||||||
EventType findByName(const QString &name);
|
EventType findByName(const QString &name);
|
||||||
EventType findById(const EventTypeId &id);
|
EventType findById(const EventTypeId &id);
|
||||||
|
|||||||
74
libguh/types/interface.cpp
Normal file
74
libguh/types/interface.cpp
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
* *
|
||||||
|
* Copyright (C) 2017 Michael Zanetti <michael.zanetti@guh.io> *
|
||||||
|
* *
|
||||||
|
* This file is part of guh. *
|
||||||
|
* *
|
||||||
|
* This library is free software; you can redistribute it and/or *
|
||||||
|
* modify it under the terms of the GNU Lesser General Public *
|
||||||
|
* License as published by the Free Software Foundation; either *
|
||||||
|
* version 2.1 of the License, or (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* This library is distributed in the hope that it will be useful, *
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||||
|
* Lesser General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU Lesser General Public *
|
||||||
|
* License along with this library; If not, see *
|
||||||
|
* <http://www.gnu.org/licenses/>. *
|
||||||
|
* *
|
||||||
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
|
#include "interface.h"
|
||||||
|
|
||||||
|
Interface::Interface(const QString &name, const ActionTypes &actionTypes, const EventTypes &eventTypes, const StateTypes &stateTypes):
|
||||||
|
m_name(name),
|
||||||
|
m_actionTypes(actionTypes),
|
||||||
|
m_eventTypes(eventTypes),
|
||||||
|
m_stateTypes(stateTypes)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
QString Interface::name() const
|
||||||
|
{
|
||||||
|
return m_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
ActionTypes Interface::actionTypes() const
|
||||||
|
{
|
||||||
|
return m_actionTypes;
|
||||||
|
}
|
||||||
|
|
||||||
|
EventTypes Interface::eventTypes() const
|
||||||
|
{
|
||||||
|
return m_eventTypes;
|
||||||
|
}
|
||||||
|
|
||||||
|
StateTypes Interface::stateTypes() const
|
||||||
|
{
|
||||||
|
return m_stateTypes;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Interface::isValid() const
|
||||||
|
{
|
||||||
|
return !m_name.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
Interfaces::Interfaces(const QList<Interface> &other)
|
||||||
|
{
|
||||||
|
foreach (const Interface &iface, other) {
|
||||||
|
append(iface);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Interface Interfaces::findByName(const QString &name)
|
||||||
|
{
|
||||||
|
foreach (const Interface &interface, *this) {
|
||||||
|
if (interface.name() == name) {
|
||||||
|
return interface;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Interface();
|
||||||
|
}
|
||||||
58
libguh/types/interface.h
Normal file
58
libguh/types/interface.h
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
* *
|
||||||
|
* Copyright (C) 2017 Michael Zanetti <michael.zanetti@guh.io> *
|
||||||
|
* *
|
||||||
|
* This file is part of guh. *
|
||||||
|
* *
|
||||||
|
* This library is free software; you can redistribute it and/or *
|
||||||
|
* modify it under the terms of the GNU Lesser General Public *
|
||||||
|
* License as published by the Free Software Foundation; either *
|
||||||
|
* version 2.1 of the License, or (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* This library is distributed in the hope that it will be useful, *
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||||
|
* Lesser General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU Lesser General Public *
|
||||||
|
* License along with this library; If not, see *
|
||||||
|
* <http://www.gnu.org/licenses/>. *
|
||||||
|
* *
|
||||||
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
|
#ifndef INTERFACE_H
|
||||||
|
#define INTERFACE_H
|
||||||
|
|
||||||
|
#include "eventtype.h"
|
||||||
|
#include "actiontype.h"
|
||||||
|
#include "statetype.h"
|
||||||
|
|
||||||
|
class Interface{
|
||||||
|
public:
|
||||||
|
Interface() = default;
|
||||||
|
Interface(const QString &name, const ActionTypes &actionTypes, const EventTypes &eventTypes, const StateTypes &stateTypes);
|
||||||
|
|
||||||
|
QString name() const;
|
||||||
|
|
||||||
|
ActionTypes actionTypes() const;
|
||||||
|
EventTypes eventTypes() const;
|
||||||
|
StateTypes stateTypes() const;
|
||||||
|
|
||||||
|
bool isValid() const;
|
||||||
|
private:
|
||||||
|
QUuid m_id;
|
||||||
|
QString m_name;
|
||||||
|
ActionTypes m_actionTypes;
|
||||||
|
EventTypes m_eventTypes;
|
||||||
|
StateTypes m_stateTypes;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Interfaces: public QList<Interface>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Interfaces() = default;
|
||||||
|
Interfaces(const QList<Interface> &other);
|
||||||
|
Interface findByName(const QString &name);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // INTERFACE_H
|
||||||
@ -38,18 +38,31 @@
|
|||||||
#include "ruleaction.h"
|
#include "ruleaction.h"
|
||||||
|
|
||||||
/*! Constructs a RuleAction with the given by \a actionTypeId and \a deviceId. */
|
/*! Constructs a RuleAction with the given by \a actionTypeId and \a deviceId. */
|
||||||
RuleAction::RuleAction(const ActionTypeId &actionTypeId, const DeviceId &deviceId) :
|
RuleAction::RuleAction(const ActionTypeId &actionTypeId, const DeviceId &deviceId, const RuleActionParamList ¶ms):
|
||||||
m_id(ActionId::createActionId()),
|
m_id(ActionId::createActionId()),
|
||||||
m_actionTypeId(actionTypeId),
|
m_actionTypeId(actionTypeId),
|
||||||
m_deviceId(deviceId)
|
m_deviceId(deviceId),
|
||||||
|
m_ruleActionParams(params)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! Constructs a RuleAction with the given by \a interface and \a interfaceAction. */
|
||||||
|
RuleAction::RuleAction(const QString &interface, const QString &interfaceAction, const RuleActionParamList ¶ms) :
|
||||||
|
m_interface(interface),
|
||||||
|
m_interfaceAction(interfaceAction),
|
||||||
|
m_ruleActionParams(params)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/*! Constructs a copy of the given \a other RuleAction. */
|
/*! Constructs a copy of the given \a other RuleAction. */
|
||||||
RuleAction::RuleAction(const RuleAction &other) :
|
RuleAction::RuleAction(const RuleAction &other) :
|
||||||
m_id(other.id()),
|
m_id(other.id()),
|
||||||
m_actionTypeId(other.actionTypeId()),
|
m_actionTypeId(other.actionTypeId()),
|
||||||
m_deviceId(other.deviceId()),
|
m_deviceId(other.deviceId()),
|
||||||
|
m_interface(other.interface()),
|
||||||
|
m_interfaceAction(other.interfaceAction()),
|
||||||
m_ruleActionParams(other.ruleActionParams())
|
m_ruleActionParams(other.ruleActionParams())
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -64,7 +77,13 @@ ActionId RuleAction::id() const
|
|||||||
/*! Return true, if the actionTypeId and the deviceId of this RuleAction are valid (set).*/
|
/*! Return true, if the actionTypeId and the deviceId of this RuleAction are valid (set).*/
|
||||||
bool RuleAction::isValid() const
|
bool RuleAction::isValid() const
|
||||||
{
|
{
|
||||||
return !m_actionTypeId.isNull() && !m_deviceId.isNull();
|
return (!m_actionTypeId.isNull() && !m_deviceId.isNull()) || (!m_interface.isEmpty() && !m_interfaceAction.isEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Returns whether this RuleAction is targetting a specific device or rather an interface. */
|
||||||
|
RuleAction::Type RuleAction::type() const
|
||||||
|
{
|
||||||
|
return (!m_actionTypeId.isNull() && !m_deviceId.isNull()) ? TypeDevice : TypeInterface;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Return true, if this RuleAction contains a \l{RuleActionParam} which is based on an EventTypeId.*/
|
/*! Return true, if this RuleAction contains a \l{RuleActionParam} which is based on an EventTypeId.*/
|
||||||
@ -103,6 +122,18 @@ DeviceId RuleAction::deviceId() const
|
|||||||
return m_deviceId;
|
return m_deviceId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! Returns the name of the interface associated with this RuleAction. */
|
||||||
|
QString RuleAction::interface() const
|
||||||
|
{
|
||||||
|
return m_interface;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Returns the name of the action of the associated interface. */
|
||||||
|
QString RuleAction::interfaceAction() const
|
||||||
|
{
|
||||||
|
return m_interfaceAction;
|
||||||
|
}
|
||||||
|
|
||||||
/*! Returns the \l{RuleActionParamList} of this RuleAction.
|
/*! Returns the \l{RuleActionParamList} of this RuleAction.
|
||||||
* \sa RuleActionParam, */
|
* \sa RuleActionParam, */
|
||||||
RuleActionParamList RuleAction::ruleActionParams() const
|
RuleActionParamList RuleAction::ruleActionParams() const
|
||||||
@ -118,7 +149,7 @@ void RuleAction::setRuleActionParams(const RuleActionParamList &ruleActionParams
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*! Returns the \l{RuleActionParam} of this RuleAction with the given \a ruleActionParamTypeId.
|
/*! Returns the \l{RuleActionParam} of this RuleAction with the given \a ruleActionParamTypeId.
|
||||||
* If there is no \l{RuleActionParam} with th given name an invalid \l{RuleActionParam} will be returnend.
|
* If there is no \l{RuleActionParam} with th given id an invalid \l{RuleActionParam} will be returnend.
|
||||||
* \sa RuleActionParam, */
|
* \sa RuleActionParam, */
|
||||||
RuleActionParam RuleAction::ruleActionParam(const ParamTypeId &ruleActionParamTypeId) const
|
RuleActionParam RuleAction::ruleActionParam(const ParamTypeId &ruleActionParamTypeId) const
|
||||||
{
|
{
|
||||||
@ -130,6 +161,19 @@ RuleActionParam RuleAction::ruleActionParam(const ParamTypeId &ruleActionParamTy
|
|||||||
return RuleActionParam(QString());
|
return RuleActionParam(QString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! Returns the \l{RuleActionParam} of this RuleAction with the given \a ruleActionParamName.
|
||||||
|
* If there is no \l{RuleActionParam} with th given name an invalid \l{RuleActionParam} will be returnend.
|
||||||
|
* \sa RuleActionParam, */
|
||||||
|
RuleActionParam RuleAction::ruleActionParam(const QString &ruleActionParamName) const
|
||||||
|
{
|
||||||
|
foreach (const RuleActionParam &ruleActionParam, m_ruleActionParams) {
|
||||||
|
if (ruleActionParam.paramName() == ruleActionParamName) {
|
||||||
|
return ruleActionParam;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return RuleActionParam(QString());
|
||||||
|
}
|
||||||
|
|
||||||
/*! Copy the data to a \l{RuleAction} from an \a other rule action. */
|
/*! Copy the data to a \l{RuleAction} from an \a other rule action. */
|
||||||
void RuleAction::operator=(const RuleAction &other)
|
void RuleAction::operator=(const RuleAction &other)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -31,12 +31,19 @@
|
|||||||
class LIBGUH_EXPORT RuleAction
|
class LIBGUH_EXPORT RuleAction
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit RuleAction(const ActionTypeId &actionTypeId = ActionTypeId(), const DeviceId &deviceId = DeviceId());
|
enum Type {
|
||||||
|
TypeDevice,
|
||||||
|
TypeInterface
|
||||||
|
};
|
||||||
|
explicit RuleAction(const ActionTypeId &actionTypeId = ActionTypeId(), const DeviceId &deviceId = DeviceId(), const RuleActionParamList ¶ms = RuleActionParamList());
|
||||||
|
explicit RuleAction(const QString &interface, const QString &interfaceAction, const RuleActionParamList ¶ms = RuleActionParamList());
|
||||||
RuleAction(const RuleAction &other);
|
RuleAction(const RuleAction &other);
|
||||||
|
|
||||||
ActionId id() const;
|
ActionId id() const;
|
||||||
bool isValid() const;
|
bool isValid() const;
|
||||||
|
|
||||||
|
Type type() const;
|
||||||
|
|
||||||
bool isEventBased() const;
|
bool isEventBased() const;
|
||||||
|
|
||||||
Action toAction() const;
|
Action toAction() const;
|
||||||
@ -44,9 +51,13 @@ public:
|
|||||||
ActionTypeId actionTypeId() const;
|
ActionTypeId actionTypeId() const;
|
||||||
DeviceId deviceId() const;
|
DeviceId deviceId() const;
|
||||||
|
|
||||||
|
QString interface() const;
|
||||||
|
QString interfaceAction() const;
|
||||||
|
|
||||||
RuleActionParamList ruleActionParams() const;
|
RuleActionParamList ruleActionParams() const;
|
||||||
void setRuleActionParams(const RuleActionParamList &ruleActionParams);
|
void setRuleActionParams(const RuleActionParamList &ruleActionParams);
|
||||||
RuleActionParam ruleActionParam(const ParamTypeId &ruleActionParamTypeId) const;
|
RuleActionParam ruleActionParam(const ParamTypeId &ruleActionParamTypeId) const;
|
||||||
|
RuleActionParam ruleActionParam(const QString &ruleActionParamName) const;
|
||||||
|
|
||||||
void operator=(const RuleAction &other);
|
void operator=(const RuleAction &other);
|
||||||
|
|
||||||
@ -54,6 +65,8 @@ private:
|
|||||||
ActionId m_id;
|
ActionId m_id;
|
||||||
ActionTypeId m_actionTypeId;
|
ActionTypeId m_actionTypeId;
|
||||||
DeviceId m_deviceId;
|
DeviceId m_deviceId;
|
||||||
|
QString m_interface;
|
||||||
|
QString m_interfaceAction;
|
||||||
RuleActionParamList m_ruleActionParams;
|
RuleActionParamList m_ruleActionParams;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -57,12 +57,28 @@ RuleActionParam::RuleActionParam(const ParamTypeId ¶mTypeId, const QVariant
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! Constructs a \l{RuleActionParam} with the given \a paramName, \a value, \a eventTypeId and \a eventParamTypeId.
|
||||||
|
* \sa Param, Event, */
|
||||||
|
RuleActionParam::RuleActionParam(const QString ¶mName, const QVariant &value, const EventTypeId &eventTypeId, const ParamTypeId &eventParamTypeId):
|
||||||
|
m_paramName(paramName),
|
||||||
|
m_value(value),
|
||||||
|
m_eventTypeId(eventTypeId),
|
||||||
|
m_eventParamTypeId(eventParamTypeId)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/*! Returns the \l ParamTypeId of this \l RuleActionParam. */
|
/*! Returns the \l ParamTypeId of this \l RuleActionParam. */
|
||||||
ParamTypeId RuleActionParam::paramTypeId() const
|
ParamTypeId RuleActionParam::paramTypeId() const
|
||||||
{
|
{
|
||||||
return m_paramTypeId;
|
return m_paramTypeId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString RuleActionParam::paramName() const
|
||||||
|
{
|
||||||
|
return m_paramName;
|
||||||
|
}
|
||||||
|
|
||||||
/*! Returns the eventParamTypeId of this RuleActionParam. */
|
/*! Returns the eventParamTypeId of this RuleActionParam. */
|
||||||
ParamTypeId RuleActionParam::eventParamTypeId() const
|
ParamTypeId RuleActionParam::eventParamTypeId() const
|
||||||
{
|
{
|
||||||
@ -136,6 +152,17 @@ bool RuleActionParamList::hasParam(const ParamTypeId &ruleActionParamTypeId) con
|
|||||||
return m_ids.contains(ruleActionParamTypeId);
|
return m_ids.contains(ruleActionParamTypeId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! Returns true if this \l{RuleActionParamList} contains a \l{RuleActionParam} with the given \a ruleActionParamName. */
|
||||||
|
bool RuleActionParamList::hasParam(const QString &ruleActionParamName) const
|
||||||
|
{
|
||||||
|
foreach (const RuleActionParam ¶m, *this) {
|
||||||
|
if (param.paramName() == ruleActionParamName) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/*! Returns the value of the \l{RuleActionParam} with the given \a ruleActionParamTypeId. */
|
/*! Returns the value of the \l{RuleActionParam} with the given \a ruleActionParamTypeId. */
|
||||||
QVariant RuleActionParamList::paramValue(const ParamTypeId &ruleActionParamTypeId) const
|
QVariant RuleActionParamList::paramValue(const ParamTypeId &ruleActionParamTypeId) const
|
||||||
{
|
{
|
||||||
|
|||||||
@ -36,9 +36,11 @@ class LIBGUH_EXPORT RuleActionParam
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
RuleActionParam(const Param ¶m = Param());
|
RuleActionParam(const Param ¶m = Param());
|
||||||
RuleActionParam(const ParamTypeId ¶mTypeId, const QVariant &value = QVariant(), const EventTypeId &eventTypeId = EventTypeId(), const ParamTypeId &eventParamName = ParamTypeId());
|
RuleActionParam(const ParamTypeId ¶mTypeId, const QVariant &value = QVariant(), const EventTypeId &eventTypeId = EventTypeId(), const ParamTypeId &eventParamTypeId = ParamTypeId());
|
||||||
|
RuleActionParam(const QString ¶mName, const QVariant &value = QVariant(), const EventTypeId &eventTypeId = EventTypeId(), const ParamTypeId &eventParamTypeId = ParamTypeId());
|
||||||
|
|
||||||
ParamTypeId paramTypeId() const;
|
ParamTypeId paramTypeId() const;
|
||||||
|
QString paramName() const;
|
||||||
|
|
||||||
ParamTypeId eventParamTypeId() const;
|
ParamTypeId eventParamTypeId() const;
|
||||||
void setEventParamTypeId(const ParamTypeId &eventParamTypeId);
|
void setEventParamTypeId(const ParamTypeId &eventParamTypeId);
|
||||||
@ -53,6 +55,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
ParamTypeId m_paramTypeId;
|
ParamTypeId m_paramTypeId;
|
||||||
|
QString m_paramName;
|
||||||
QVariant m_value;
|
QVariant m_value;
|
||||||
EventTypeId m_eventTypeId;
|
EventTypeId m_eventTypeId;
|
||||||
ParamTypeId m_eventParamTypeId;
|
ParamTypeId m_eventParamTypeId;
|
||||||
@ -65,6 +68,7 @@ class LIBGUH_EXPORT RuleActionParamList: public QList<RuleActionParam>
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
bool hasParam(const ParamTypeId &ruleActionParamTypeId) const;
|
bool hasParam(const ParamTypeId &ruleActionParamTypeId) const;
|
||||||
|
bool hasParam(const QString &ruleActionParamName) const;
|
||||||
QVariant paramValue(const ParamTypeId &ruleActionParamName) const;
|
QVariant paramValue(const ParamTypeId &ruleActionParamName) const;
|
||||||
bool setParamValue(const ParamTypeId &ruleActionParamTypeId, const QVariant &value);
|
bool setParamValue(const ParamTypeId &ruleActionParamTypeId, const QVariant &value);
|
||||||
RuleActionParamList operator<<(const RuleActionParam &ruleActionParam);
|
RuleActionParamList operator<<(const RuleActionParam &ruleActionParam);
|
||||||
|
|||||||
@ -92,6 +92,7 @@ private:
|
|||||||
class StateTypes: public QList<StateType>
|
class StateTypes: public QList<StateType>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
StateTypes() = default;
|
||||||
StateTypes(const QList<StateType> &other);
|
StateTypes(const QList<StateType> &other);
|
||||||
StateType findByName(const QString &name);
|
StateType findByName(const QString &name);
|
||||||
StateType findById(const StateTypeId &id);
|
StateType findById(const StateTypeId &id);
|
||||||
|
|||||||
@ -31,7 +31,7 @@
|
|||||||
"name": "mock",
|
"name": "mock",
|
||||||
"displayName": "Mock Device",
|
"displayName": "Mock Device",
|
||||||
"deviceIcon": "Tune",
|
"deviceIcon": "Tune",
|
||||||
"interfaces": ["gateway", "light", "mediacontroller"],
|
"interfaces": ["gateway", "light", "mediacontroller", "battery"],
|
||||||
"basicTags": [
|
"basicTags": [
|
||||||
"Device",
|
"Device",
|
||||||
"Actuator",
|
"Actuator",
|
||||||
@ -91,7 +91,36 @@
|
|||||||
"defaultValue": false,
|
"defaultValue": false,
|
||||||
"type": "bool",
|
"type": "bool",
|
||||||
"cached": false
|
"cached": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "6c8ab9a6-0164-4795-b829-f4394fe4edc4",
|
||||||
|
"name": "batteryLevel",
|
||||||
|
"displayName": "battery level",
|
||||||
|
"displayNameEvent": "battery level",
|
||||||
|
"type": "int",
|
||||||
|
"minValue": 0,
|
||||||
|
"maxValue": 100,
|
||||||
|
"defaultValue": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "580bc611-1a55-41f3-996f-8d3ccf543db3",
|
||||||
|
"name": "batteryCritical",
|
||||||
|
"displayName": "battery level critical",
|
||||||
|
"displayNameEvent": "battery level critical",
|
||||||
|
"type": "bool",
|
||||||
|
"defaultValue": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "064aed0d-da4c-49d4-b236-60f97e98ff84",
|
||||||
|
"name": "power",
|
||||||
|
"displayName": "powered",
|
||||||
|
"displayNameEvent": "powered changed",
|
||||||
|
"displayNameAction": "set power",
|
||||||
|
"type": "bool",
|
||||||
|
"defaultValue": false,
|
||||||
|
"writable": true
|
||||||
}
|
}
|
||||||
|
|
||||||
],
|
],
|
||||||
"eventTypes": [
|
"eventTypes": [
|
||||||
{
|
{
|
||||||
|
|||||||
@ -24,8 +24,8 @@
|
|||||||
#include "httpdaemon.h"
|
#include "httpdaemon.h"
|
||||||
|
|
||||||
#include "plugin/device.h"
|
#include "plugin/device.h"
|
||||||
#include "plugin/deviceclass.h"
|
|
||||||
#include "plugin/deviceplugin.h"
|
#include "plugin/deviceplugin.h"
|
||||||
|
#include "types/deviceclass.h"
|
||||||
#include "types/statetype.h"
|
#include "types/statetype.h"
|
||||||
#include "extern-plugininfo.h"
|
#include "extern-plugininfo.h"
|
||||||
|
|
||||||
@ -137,7 +137,13 @@ QString HttpDaemon::generateHeader()
|
|||||||
|
|
||||||
QString HttpDaemon::generateWebPage()
|
QString HttpDaemon::generateWebPage()
|
||||||
{
|
{
|
||||||
DeviceClass deviceClass = m_plugin->supportedDevices().first();
|
DeviceClass deviceClass;
|
||||||
|
foreach (const DeviceClass &dc, m_plugin->supportedDevices()) {
|
||||||
|
if (dc.id() == m_device->deviceClassId()) {
|
||||||
|
deviceClass = dc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Q_ASSERT(deviceClass.isValid());
|
||||||
|
|
||||||
QString body = QString(
|
QString body = QString(
|
||||||
"<html>"
|
"<html>"
|
||||||
@ -156,7 +162,7 @@ QString HttpDaemon::generateWebPage()
|
|||||||
for (int i = 0; i < deviceClass.stateTypes().count(); ++i) {
|
for (int i = 0; i < deviceClass.stateTypes().count(); ++i) {
|
||||||
body.append("<tr>");
|
body.append("<tr>");
|
||||||
body.append("<form action=\"/setstate\" method=\"get\">");
|
body.append("<form action=\"/setstate\" method=\"get\">");
|
||||||
const StateType &stateType = deviceClass.stateTypes().at(i);
|
StateType stateType = deviceClass.stateTypes().at(i);
|
||||||
body.append("<td>" + stateType.name() + "</td>");
|
body.append("<td>" + stateType.name() + "</td>");
|
||||||
body.append(QString("<td><input type='input'' name='%1' value='%2'></td>").arg(stateType.id().toString()).arg(m_device->states().at(i).value().toString()));
|
body.append(QString("<td><input type='input'' name='%1' value='%2'></td>").arg(stateType.id().toString()).arg(m_device->states().at(i).value().toString()));
|
||||||
body.append("<td><input type=submit value='Set State'/></td>");
|
body.append("<td><input type=submit value='Set State'/></td>");
|
||||||
@ -170,14 +176,14 @@ QString HttpDaemon::generateWebPage()
|
|||||||
|
|
||||||
body.append("<table>");
|
body.append("<table>");
|
||||||
for (int i = 0; i < deviceClass.eventTypes().count(); ++i) {
|
for (int i = 0; i < deviceClass.eventTypes().count(); ++i) {
|
||||||
const EventType &eventType = deviceClass.eventTypes().at(i);
|
EventType eventType = deviceClass.eventTypes().at(i);
|
||||||
body.append(QString(
|
body.append(QString(
|
||||||
"<tr>"
|
"<tr>"
|
||||||
"<form action=\"/generateevent\" method=\"get\">"
|
"<form action=\"/generateevent\" method=\"get\">"
|
||||||
"<td>%1<input type='hidden' name='eventtypeid' value='%2'/></td>"
|
"<td>%1<input type='hidden' name='eventtypeid' value='%2'/></td>"
|
||||||
"<td>").arg(eventType.name()).arg(eventType.id().toString()));
|
"<td>").arg(eventType.name()).arg(eventType.id().toString()));
|
||||||
if (!eventType.name().endsWith(" changed")) {
|
if (!eventType.displayName().endsWith(" changed")) {
|
||||||
body.append("<input type='submit' value='Generate'/>");
|
body.append(QStringLiteral("<input type='submit' value='Generate'/>"));
|
||||||
}
|
}
|
||||||
body.append("</td>"
|
body.append("</td>"
|
||||||
"</form>"
|
"</form>"
|
||||||
@ -211,7 +217,6 @@ QString HttpDaemon::generateWebPage()
|
|||||||
}
|
}
|
||||||
body.append("</table>");
|
body.append("</table>");
|
||||||
|
|
||||||
|
|
||||||
body.append("</body></html>\n");
|
body.append("</body></html>\n");
|
||||||
|
|
||||||
return generateHeader() + body;
|
return generateHeader() + body;
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
1.0
|
1.1
|
||||||
{
|
{
|
||||||
"methods": {
|
"methods": {
|
||||||
"Actions.ExecuteAction": {
|
"Actions.ExecuteAction": {
|
||||||
@ -1152,8 +1152,10 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"EventDescriptor": {
|
"EventDescriptor": {
|
||||||
"deviceId": "Uuid",
|
"o:deviceId": "Uuid",
|
||||||
"eventTypeId": "Uuid",
|
"o:eventTypeId": "Uuid",
|
||||||
|
"o:interface": "String",
|
||||||
|
"o:interfaceEvent": "String",
|
||||||
"o:paramDescriptors": [
|
"o:paramDescriptors": [
|
||||||
"$ref:ParamDescriptor"
|
"$ref:ParamDescriptor"
|
||||||
]
|
]
|
||||||
@ -1325,8 +1327,10 @@
|
|||||||
"timeDescriptor": "$ref:TimeDescriptor"
|
"timeDescriptor": "$ref:TimeDescriptor"
|
||||||
},
|
},
|
||||||
"RuleAction": {
|
"RuleAction": {
|
||||||
"actionTypeId": "Uuid",
|
"o:actionTypeId": "Uuid",
|
||||||
"deviceId": "Uuid",
|
"o:deviceId": "Uuid",
|
||||||
|
"o:interface": "String",
|
||||||
|
"o:interfaceAction": "String",
|
||||||
"o:ruleActionParams": [
|
"o:ruleActionParams": [
|
||||||
"$ref:RuleActionParam"
|
"$ref:RuleActionParam"
|
||||||
]
|
]
|
||||||
@ -1334,8 +1338,9 @@
|
|||||||
"RuleActionParam": {
|
"RuleActionParam": {
|
||||||
"o:eventParamTypeId": "Uuid",
|
"o:eventParamTypeId": "Uuid",
|
||||||
"o:eventTypeId": "Uuid",
|
"o:eventTypeId": "Uuid",
|
||||||
"o:value": "$ref:BasicType",
|
"o:paramName": "String",
|
||||||
"paramTypeId": "Uuid"
|
"o:paramTypeId": "Uuid",
|
||||||
|
"o:value": "$ref:BasicType"
|
||||||
},
|
},
|
||||||
"RuleDescription": {
|
"RuleDescription": {
|
||||||
"active": "Bool",
|
"active": "Bool",
|
||||||
@ -1364,7 +1369,8 @@
|
|||||||
"RuleErrorInvalidCalendarItem",
|
"RuleErrorInvalidCalendarItem",
|
||||||
"RuleErrorInvalidTimeEventItem",
|
"RuleErrorInvalidTimeEventItem",
|
||||||
"RuleErrorContainsEventBasesAction",
|
"RuleErrorContainsEventBasesAction",
|
||||||
"RuleErrorNoExitActions"
|
"RuleErrorNoExitActions",
|
||||||
|
"RuleErrorInterfaceNotFound"
|
||||||
],
|
],
|
||||||
"ServerConfiguration": {
|
"ServerConfiguration": {
|
||||||
"address": "String",
|
"address": "String",
|
||||||
|
|||||||
@ -241,9 +241,13 @@ void TestDevices::verifyInterfaces()
|
|||||||
QVERIFY(!mockDevice.isEmpty());
|
QVERIFY(!mockDevice.isEmpty());
|
||||||
|
|
||||||
QVariantList interfaces = mockDevice.value("interfaces").toList();
|
QVariantList interfaces = mockDevice.value("interfaces").toList();
|
||||||
// Must contain gateway, but must not contain anything else as device manager should filter it away
|
// Must contain gateway, light and battery, but must not contain mediacontroller as the device manager should filter
|
||||||
QCOMPARE(interfaces.count() == 1, true);
|
// that away because it doesn't implement all the required states.
|
||||||
|
QCOMPARE(interfaces.count(), 3);
|
||||||
QVERIFY(interfaces.contains("gateway"));
|
QVERIFY(interfaces.contains("gateway"));
|
||||||
|
QVERIFY(interfaces.contains("battery"));
|
||||||
|
QVERIFY(interfaces.contains("light"));
|
||||||
|
QVERIFY(!interfaces.contains("mediacontroller"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestDevices::addConfiguredDevice_data()
|
void TestDevices::addConfiguredDevice_data()
|
||||||
@ -631,25 +635,33 @@ void TestDevices::parentChildDevices()
|
|||||||
void TestDevices::getActionTypes_data()
|
void TestDevices::getActionTypes_data()
|
||||||
{
|
{
|
||||||
QTest::addColumn<DeviceClassId>("deviceClassId");
|
QTest::addColumn<DeviceClassId>("deviceClassId");
|
||||||
QTest::addColumn<int>("resultCount");
|
QTest::addColumn<QList<ActionTypeId> >("actionTypeTestData");
|
||||||
|
|
||||||
QTest::newRow("valid deviceclass") << mockDeviceClassId << 5;
|
QTest::newRow("valid deviceclass") << mockDeviceClassId
|
||||||
QTest::newRow("invalid deviceclass") << DeviceClassId("094f8024-5caa-48c1-ab6a-de486a92088f") << 0;
|
<< (QList<ActionTypeId>() << mockActionIdAsync << mockActionIdAsyncFailing << mockActionIdFailing << mockActionIdNoParams << mockActionIdPower << mockActionIdWithParams);
|
||||||
|
QTest::newRow("invalid deviceclass") << DeviceClassId("094f8024-5caa-48c1-ab6a-de486a92088f") << QList<ActionTypeId>();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestDevices::getActionTypes()
|
void TestDevices::getActionTypes()
|
||||||
{
|
{
|
||||||
QFETCH(DeviceClassId, deviceClassId);
|
QFETCH(DeviceClassId, deviceClassId);
|
||||||
QFETCH(int, resultCount);
|
QFETCH(QList<ActionTypeId>, actionTypeTestData);
|
||||||
|
|
||||||
QVariantMap params;
|
QVariantMap params;
|
||||||
params.insert("deviceClassId", deviceClassId);
|
params.insert("deviceClassId", deviceClassId);
|
||||||
QVariant response = injectAndWait("Devices.GetActionTypes", params);
|
QVariant response = injectAndWait("Devices.GetActionTypes", params);
|
||||||
|
|
||||||
QVariantList actionTypes = response.toMap().value("params").toMap().value("actionTypes").toList();
|
QVariantList actionTypes = response.toMap().value("params").toMap().value("actionTypes").toList();
|
||||||
QCOMPARE(actionTypes.count(), resultCount);
|
QCOMPARE(actionTypes.count(), actionTypeTestData.count());
|
||||||
if (resultCount > 0) {
|
foreach (const ActionTypeId &testDataId, actionTypeTestData) {
|
||||||
QCOMPARE(actionTypes.first().toMap().value("id").toString(), mockActionIdWithParams.toString());
|
bool found = false;
|
||||||
|
foreach (const QVariant &at, actionTypes) {
|
||||||
|
if (testDataId.toString() == at.toMap().value("id").toString()) {
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
QVERIFY(found);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -658,7 +670,7 @@ void TestDevices::getEventTypes_data()
|
|||||||
QTest::addColumn<DeviceClassId>("deviceClassId");
|
QTest::addColumn<DeviceClassId>("deviceClassId");
|
||||||
QTest::addColumn<int>("resultCount");
|
QTest::addColumn<int>("resultCount");
|
||||||
|
|
||||||
QTest::newRow("valid deviceclass") << mockDeviceClassId << 4;
|
QTest::newRow("valid deviceclass") << mockDeviceClassId << 7;
|
||||||
QTest::newRow("invalid deviceclass") << DeviceClassId("094f8024-5caa-48c1-ab6a-de486a92088f") << 0;
|
QTest::newRow("invalid deviceclass") << DeviceClassId("094f8024-5caa-48c1-ab6a-de486a92088f") << 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -683,7 +695,7 @@ void TestDevices::getStateTypes_data()
|
|||||||
QTest::addColumn<DeviceClassId>("deviceClassId");
|
QTest::addColumn<DeviceClassId>("deviceClassId");
|
||||||
QTest::addColumn<int>("resultCount");
|
QTest::addColumn<int>("resultCount");
|
||||||
|
|
||||||
QTest::newRow("valid deviceclass") << mockDeviceClassId << 2;
|
QTest::newRow("valid deviceclass") << mockDeviceClassId << 5;
|
||||||
QTest::newRow("invalid deviceclass") << DeviceClassId("094f8024-5caa-48c1-ab6a-de486a92088f") << 0;
|
QTest::newRow("invalid deviceclass") << DeviceClassId("094f8024-5caa-48c1-ab6a-de486a92088f") << 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -784,7 +796,7 @@ void TestDevices::getStateValues()
|
|||||||
QCOMPARE(response.toMap().value("params").toMap().value("deviceError").toString(), JsonTypes::deviceErrorToString(statusCode));
|
QCOMPARE(response.toMap().value("params").toMap().value("deviceError").toString(), JsonTypes::deviceErrorToString(statusCode));
|
||||||
if (statusCode == DeviceManager::DeviceErrorNoError) {
|
if (statusCode == DeviceManager::DeviceErrorNoError) {
|
||||||
QVariantList values = response.toMap().value("params").toMap().value("values").toList();
|
QVariantList values = response.toMap().value("params").toMap().value("values").toList();
|
||||||
QCOMPARE(values.count(), 2); // Mock device has two states...
|
QCOMPARE(values.count(), 5); // Mock device has two states...
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1231,6 +1243,8 @@ void TestDevices::removeAutoDevice()
|
|||||||
QVERIFY2(devices.count() > 0, "There needs to be at least one auto-created Mock Device for this test");
|
QVERIFY2(devices.count() > 0, "There needs to be at least one auto-created Mock Device for this test");
|
||||||
device = devices.first();
|
device = devices.first();
|
||||||
|
|
||||||
|
DeviceClass dc = GuhCore::instance()->deviceManager()->findDeviceClass(device->deviceClassId());
|
||||||
|
|
||||||
// trigger disappear signal in mock device
|
// trigger disappear signal in mock device
|
||||||
spy.clear();
|
spy.clear();
|
||||||
port = device->paramValue(httpportParamTypeId).toInt();
|
port = device->paramValue(httpportParamTypeId).toInt();
|
||||||
|
|||||||
@ -56,6 +56,8 @@ EventTypeId mockEvent1Id = EventTypeId("45bf3752-0fc6-46b9-89fd-ffd878b5b22b");
|
|||||||
EventTypeId mockEvent2Id = EventTypeId("863d5920-b1cf-4eb9-88bd-8f7b8583b1cf");
|
EventTypeId mockEvent2Id = EventTypeId("863d5920-b1cf-4eb9-88bd-8f7b8583b1cf");
|
||||||
StateTypeId mockIntStateId = StateTypeId("80baec19-54de-4948-ac46-31eabfaceb83");
|
StateTypeId mockIntStateId = StateTypeId("80baec19-54de-4948-ac46-31eabfaceb83");
|
||||||
StateTypeId mockBoolStateId = StateTypeId("9dd6a97c-dfd1-43dc-acbd-367932742310");
|
StateTypeId mockBoolStateId = StateTypeId("9dd6a97c-dfd1-43dc-acbd-367932742310");
|
||||||
|
StateTypeId mockBatteryCriticalStateId = StateTypeId("580bc611-1a55-41f3-996f-8d3ccf543db3");
|
||||||
|
ActionTypeId mockActionIdPower = ActionTypeId("064aed0d-da4c-49d4-b236-60f97e98ff84");
|
||||||
ActionTypeId mockActionIdWithParams = ActionTypeId("dea0f4e1-65e3-4981-8eaa-2701c53a9185");
|
ActionTypeId mockActionIdWithParams = ActionTypeId("dea0f4e1-65e3-4981-8eaa-2701c53a9185");
|
||||||
ActionTypeId mockActionIdNoParams = ActionTypeId("defd3ed6-1a0d-400b-8879-a0202cf39935");
|
ActionTypeId mockActionIdNoParams = ActionTypeId("defd3ed6-1a0d-400b-8879-a0202cf39935");
|
||||||
ActionTypeId mockActionIdAsync = ActionTypeId("fbae06d3-7666-483e-a39e-ec50fe89054e");
|
ActionTypeId mockActionIdAsync = ActionTypeId("fbae06d3-7666-483e-a39e-ec50fe89054e");
|
||||||
|
|||||||
@ -47,6 +47,7 @@ extern DeviceClassId mockDeviceDiscoveryClassId;
|
|||||||
extern DeviceClassId mockDeviceAsyncSetupClassId;
|
extern DeviceClassId mockDeviceAsyncSetupClassId;
|
||||||
extern DeviceClassId mockDeviceBrokenClassId;
|
extern DeviceClassId mockDeviceBrokenClassId;
|
||||||
extern DeviceClassId mockDeviceBrokenAsyncSetupClassId;
|
extern DeviceClassId mockDeviceBrokenAsyncSetupClassId;
|
||||||
|
extern ActionTypeId mockActionIdPower;
|
||||||
extern ActionTypeId mockActionIdWithParams;
|
extern ActionTypeId mockActionIdWithParams;
|
||||||
extern ActionTypeId mockActionIdNoParams;
|
extern ActionTypeId mockActionIdNoParams;
|
||||||
extern ActionTypeId mockActionIdAsync;
|
extern ActionTypeId mockActionIdAsync;
|
||||||
@ -55,6 +56,7 @@ extern ActionTypeId mockActionIdAsyncFailing;
|
|||||||
extern EventTypeId mockEvent1Id;
|
extern EventTypeId mockEvent1Id;
|
||||||
extern EventTypeId mockEvent2Id;
|
extern EventTypeId mockEvent2Id;
|
||||||
extern StateTypeId mockIntStateId;
|
extern StateTypeId mockIntStateId;
|
||||||
|
extern StateTypeId mockBatteryCriticalStateId;
|
||||||
extern StateTypeId mockBoolStateId;
|
extern StateTypeId mockBoolStateId;
|
||||||
|
|
||||||
// ParamTypes from mock devices
|
// ParamTypes from mock devices
|
||||||
|
|||||||
@ -99,6 +99,8 @@ private slots:
|
|||||||
void testRuleActionParams_data();
|
void testRuleActionParams_data();
|
||||||
void testRuleActionParams();
|
void testRuleActionParams();
|
||||||
|
|
||||||
|
void testInterfaceBasedRule();
|
||||||
|
|
||||||
void testHousekeeping_data();
|
void testHousekeeping_data();
|
||||||
void testHousekeeping();
|
void testHousekeeping();
|
||||||
|
|
||||||
@ -488,7 +490,7 @@ void TestRules::addRemoveRules_data()
|
|||||||
QTest::newRow("valid rule. diabled, 1 EventDescriptor, StateEvaluator, 1 Action, name") << false << validActionNoParams << QVariantMap() << validEventDescriptor1 << QVariantList() << validStateEvaluator << RuleEngine::RuleErrorNoError << true << "TestRule";
|
QTest::newRow("valid rule. diabled, 1 EventDescriptor, StateEvaluator, 1 Action, name") << false << validActionNoParams << QVariantMap() << validEventDescriptor1 << QVariantList() << validStateEvaluator << RuleEngine::RuleErrorNoError << true << "TestRule";
|
||||||
QTest::newRow("valid rule. 2 EventDescriptors, 1 Action, name") << true << validActionNoParams << QVariantMap() << QVariantMap() << eventDescriptorList << validStateEvaluator << RuleEngine::RuleErrorNoError << true << "TestRule";
|
QTest::newRow("valid rule. 2 EventDescriptors, 1 Action, name") << true << validActionNoParams << QVariantMap() << QVariantMap() << eventDescriptorList << validStateEvaluator << RuleEngine::RuleErrorNoError << true << "TestRule";
|
||||||
QTest::newRow("invalid action") << true << invalidAction << QVariantMap() << validEventDescriptor1 << QVariantList() << validStateEvaluator << RuleEngine::RuleErrorActionTypeNotFound << false << "TestRule";
|
QTest::newRow("invalid action") << true << invalidAction << QVariantMap() << validEventDescriptor1 << QVariantList() << validStateEvaluator << RuleEngine::RuleErrorActionTypeNotFound << false << "TestRule";
|
||||||
QTest::newRow("invalid event descriptor") << true << validActionNoParams << QVariantMap() << invalidEventDescriptor << QVariantList() << validStateEvaluator << RuleEngine::RuleErrorDeviceNotFound << false << "TestRule";
|
QTest::newRow("invalid event descriptor") << true << validActionNoParams << QVariantMap() << invalidEventDescriptor << QVariantList() << validStateEvaluator << RuleEngine::RuleErrorEventTypeNotFound << false << "TestRule";
|
||||||
QTest::newRow("invalid StateDescriptor") << true << validActionNoParams << QVariantMap() << validEventDescriptor1 << QVariantList() << invalidStateEvaluator << RuleEngine::RuleErrorInvalidParameter << true << "TestRule";
|
QTest::newRow("invalid StateDescriptor") << true << validActionNoParams << QVariantMap() << validEventDescriptor1 << QVariantList() << invalidStateEvaluator << RuleEngine::RuleErrorInvalidParameter << true << "TestRule";
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2065,6 +2067,44 @@ void TestRules::testRuleActionParams()
|
|||||||
verifyRuleError(response, error);
|
verifyRuleError(response, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TestRules::testInterfaceBasedRule()
|
||||||
|
{
|
||||||
|
QVariantMap powerAction;
|
||||||
|
powerAction.insert("interface", "light");
|
||||||
|
powerAction.insert("interfaceAction", "power");
|
||||||
|
QVariantMap powerActionParam;
|
||||||
|
powerActionParam.insert("paramName", "power");
|
||||||
|
powerActionParam.insert("value", true);
|
||||||
|
powerAction.insert("ruleActionParams", QVariantList() << powerActionParam);
|
||||||
|
|
||||||
|
QVariantMap lowBatteryEvent;
|
||||||
|
lowBatteryEvent.insert("interface", "battery");
|
||||||
|
lowBatteryEvent.insert("interfaceEvent", "batteryCritical");
|
||||||
|
|
||||||
|
QVariantMap addRuleParams;
|
||||||
|
addRuleParams.insert("name", "TestInterfaceBasedRule");
|
||||||
|
addRuleParams.insert("enabled", true);
|
||||||
|
addRuleParams.insert("actions", QVariantList() << powerAction);
|
||||||
|
addRuleParams.insert("eventDescriptors", QVariantList() << lowBatteryEvent);
|
||||||
|
|
||||||
|
QVariant response = injectAndWait("Rules.AddRule", addRuleParams);
|
||||||
|
|
||||||
|
|
||||||
|
// Change the state
|
||||||
|
QNetworkAccessManager nam;
|
||||||
|
QSignalSpy spy(&nam, SIGNAL(finished(QNetworkReply*)));
|
||||||
|
|
||||||
|
// state battery critical state to true
|
||||||
|
qDebug() << "setting battery critical state to true";
|
||||||
|
QNetworkRequest request(QUrl(QString("http://localhost:%1/setstate?%2=%3").arg(m_mockDevice1Port).arg(mockBatteryCriticalStateId.toString()).arg(true)));
|
||||||
|
QNetworkReply *reply = nam.get(request);
|
||||||
|
spy.wait();
|
||||||
|
QCOMPARE(spy.count(), 1);
|
||||||
|
reply->deleteLater();
|
||||||
|
|
||||||
|
qDebug() << "response" << response;
|
||||||
|
}
|
||||||
|
|
||||||
void TestRules::testHousekeeping_data()
|
void TestRules::testHousekeeping_data()
|
||||||
{
|
{
|
||||||
QTest::addColumn<bool>("testAction");
|
QTest::addColumn<bool>("testAction");
|
||||||
|
|||||||
Reference in New Issue
Block a user