add device parent child relation
add remove policy to REST expand remove policy
This commit is contained in:
parent
fb6aa3e068
commit
fc9b6f1887
@ -741,6 +741,18 @@ QList<Device *> DeviceManager::findConfiguredDevices(const DeviceClassId &device
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! Returns all child \l{Device}{Devices} of the given \a device. */
|
||||||
|
QList<Device *> DeviceManager::findChildDevices(Device *device) const
|
||||||
|
{
|
||||||
|
QList<Device *> ret;
|
||||||
|
foreach (Device *d, m_configuredDevices) {
|
||||||
|
if (d->parentId() == device->id()) {
|
||||||
|
ret.append(d);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/*! For conveninece, this returns the \l{DeviceClass} with the id given by \a deviceClassId.
|
/*! For conveninece, this returns the \l{DeviceClass} with the id given by \a deviceClassId.
|
||||||
* Note: The returned \l{DeviceClass} may be invalid. */
|
* Note: The returned \l{DeviceClass} may be invalid. */
|
||||||
DeviceClass DeviceManager::findDeviceClass(const DeviceClassId &deviceClassId) const
|
DeviceClass DeviceManager::findDeviceClass(const DeviceClassId &deviceClassId) const
|
||||||
@ -881,6 +893,7 @@ void DeviceManager::loadConfiguredDevices()
|
|||||||
settings.beginGroup(idString);
|
settings.beginGroup(idString);
|
||||||
Device *device = new Device(PluginId(settings.value("pluginid").toString()), DeviceId(idString), DeviceClassId(settings.value("deviceClassId").toString()), this);
|
Device *device = new Device(PluginId(settings.value("pluginid").toString()), DeviceId(idString), DeviceClassId(settings.value("deviceClassId").toString()), this);
|
||||||
device->setName(settings.value("devicename").toString());
|
device->setName(settings.value("devicename").toString());
|
||||||
|
device->setParentId(DeviceId(settings.value("parentid", QUuid()).toString()));
|
||||||
|
|
||||||
ParamList params;
|
ParamList params;
|
||||||
settings.beginGroup("Params");
|
settings.beginGroup("Params");
|
||||||
@ -914,6 +927,9 @@ void DeviceManager::storeConfiguredDevices()
|
|||||||
settings.setValue("devicename", device->name());
|
settings.setValue("devicename", device->name());
|
||||||
settings.setValue("deviceClassId", device->deviceClassId().toString());
|
settings.setValue("deviceClassId", device->deviceClassId().toString());
|
||||||
settings.setValue("pluginid", device->pluginId().toString());
|
settings.setValue("pluginid", device->pluginId().toString());
|
||||||
|
if (!device->parentId().isNull())
|
||||||
|
settings.setValue("parentid", device->parentId().toString());
|
||||||
|
|
||||||
settings.beginGroup("Params");
|
settings.beginGroup("Params");
|
||||||
foreach (const Param ¶m, device->params()) {
|
foreach (const Param ¶m, device->params()) {
|
||||||
settings.setValue(param.name(), param.value());
|
settings.setValue(param.name(), param.value());
|
||||||
|
|||||||
@ -82,6 +82,8 @@ public:
|
|||||||
DeviceErrorAuthentificationFailure,
|
DeviceErrorAuthentificationFailure,
|
||||||
DeviceErrorAsync,
|
DeviceErrorAsync,
|
||||||
DeviceErrorDeviceInUse,
|
DeviceErrorDeviceInUse,
|
||||||
|
DeviceErrorDeviceInRule,
|
||||||
|
DeviceErrorDeviceIsChild,
|
||||||
DeviceErrorPairingTransactionIdNotFound,
|
DeviceErrorPairingTransactionIdNotFound,
|
||||||
DeviceErrorParameterNotWritable
|
DeviceErrorParameterNotWritable
|
||||||
};
|
};
|
||||||
@ -119,7 +121,8 @@ public:
|
|||||||
DeviceError removeConfiguredDevice(const DeviceId &deviceId);
|
DeviceError removeConfiguredDevice(const DeviceId &deviceId);
|
||||||
|
|
||||||
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 *> findChildDevices(Device *device) const;
|
||||||
DeviceClass findDeviceClass(const DeviceClassId &deviceClassId) const;
|
DeviceClass findDeviceClass(const DeviceClassId &deviceClassId) const;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
|||||||
@ -45,7 +45,7 @@ void UpnpDiscoveryRequest::discover()
|
|||||||
m_upnpDiscovery->sendToMulticast(ssdpSearchMessage);
|
m_upnpDiscovery->sendToMulticast(ssdpSearchMessage);
|
||||||
qCDebug(dcHardware) << "--> UPnP discovery called.";
|
qCDebug(dcHardware) << "--> UPnP discovery called.";
|
||||||
|
|
||||||
m_timer->start(3000);
|
m_timer->start(5000);
|
||||||
}
|
}
|
||||||
|
|
||||||
void UpnpDiscoveryRequest::addDeviceDescriptor(const UpnpDeviceDescriptor &deviceDescriptor)
|
void UpnpDiscoveryRequest::addDeviceDescriptor(const UpnpDeviceDescriptor &deviceDescriptor)
|
||||||
|
|||||||
@ -154,7 +154,7 @@ bool Device::hasParam(const QString ¶mName) const
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Sets the \a states of this Device. It must match the \l{StateType} description in the associated \l{DeviceClass}. */
|
DeviceId m_id;
|
||||||
void Device::setStates(const QList<State> &states)
|
void Device::setStates(const QList<State> &states)
|
||||||
{
|
{
|
||||||
m_states = states;
|
m_states = states;
|
||||||
@ -211,6 +211,22 @@ State Device::state(const StateTypeId &stateTypeId) const
|
|||||||
return State(StateTypeId(), DeviceId());
|
return State(StateTypeId(), DeviceId());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! Returns the \l{DeviceId} of the parent Device from Device. If the parentId
|
||||||
|
is not set, this device is a parent device.
|
||||||
|
*/
|
||||||
|
DeviceId Device::parentId() const
|
||||||
|
{
|
||||||
|
return m_parentId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Sets the \a parentId of this Device. If the parentId
|
||||||
|
is not set, this device is a parent device.
|
||||||
|
*/
|
||||||
|
void Device::setParentId(const DeviceId &parentId)
|
||||||
|
{
|
||||||
|
m_parentId = parentId;
|
||||||
|
}
|
||||||
|
|
||||||
/*! Returns true, if setup of this Device is already completed. */
|
/*! Returns true, if setup of this Device is already completed. */
|
||||||
bool Device::setupComplete() const
|
bool Device::setupComplete() const
|
||||||
{
|
{
|
||||||
|
|||||||
@ -32,7 +32,6 @@
|
|||||||
#include <QUuid>
|
#include <QUuid>
|
||||||
#include <QVariant>
|
#include <QVariant>
|
||||||
|
|
||||||
|
|
||||||
class Device: public QObject
|
class Device: public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
@ -63,6 +62,9 @@ public:
|
|||||||
|
|
||||||
State state(const StateTypeId &stateTypeId) const;
|
State state(const StateTypeId &stateTypeId) const;
|
||||||
|
|
||||||
|
DeviceId parentId() const;
|
||||||
|
void setParentId(const DeviceId &parentId);
|
||||||
|
|
||||||
bool setupComplete() const;
|
bool setupComplete() const;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
@ -77,6 +79,7 @@ private:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
DeviceId m_id;
|
DeviceId m_id;
|
||||||
|
DeviceId m_parentId;
|
||||||
DeviceClassId m_deviceClassId;
|
DeviceClassId m_deviceClassId;
|
||||||
PluginId m_pluginId;
|
PluginId m_pluginId;
|
||||||
QString m_name;
|
QString m_name;
|
||||||
|
|||||||
@ -85,6 +85,7 @@ DeviceManager::DeviceError DevicePluginPhilipsHue::discoverDevices(const DeviceC
|
|||||||
{
|
{
|
||||||
Q_UNUSED(deviceClassId)
|
Q_UNUSED(deviceClassId)
|
||||||
Q_UNUSED(params)
|
Q_UNUSED(params)
|
||||||
|
|
||||||
upnpDiscover("libhue:idl");
|
upnpDiscover("libhue:idl");
|
||||||
return DeviceManager::DeviceErrorAsync;
|
return DeviceManager::DeviceErrorAsync;
|
||||||
}
|
}
|
||||||
@ -164,10 +165,9 @@ DeviceManager::DeviceSetupStatus DevicePluginPhilipsHue::setupDevice(Device *dev
|
|||||||
device->paramValue("model id").toString(),
|
device->paramValue("model id").toString(),
|
||||||
DeviceId(device->paramValue("bridge").toString()),
|
DeviceId(device->paramValue("bridge").toString()),
|
||||||
this);
|
this);
|
||||||
|
|
||||||
connect(hueLight, &HueLight::stateChanged, this, &DevicePluginPhilipsHue::lightStateChanged);
|
connect(hueLight, &HueLight::stateChanged, this, &DevicePluginPhilipsHue::lightStateChanged);
|
||||||
}
|
}
|
||||||
|
device->setParentId(device->paramValue("bridge").toString());
|
||||||
m_lights.insert(hueLight, device);
|
m_lights.insert(hueLight, device);
|
||||||
setLightName(device, device->paramValue("name").toString());
|
setLightName(device, device->paramValue("name").toString());
|
||||||
}
|
}
|
||||||
@ -181,8 +181,6 @@ void DevicePluginPhilipsHue::deviceRemoved(Device *device)
|
|||||||
HueBridge *bridge = m_bridges.key(device);
|
HueBridge *bridge = m_bridges.key(device);
|
||||||
m_bridges.remove(bridge);
|
m_bridges.remove(bridge);
|
||||||
bridge->deleteLater();
|
bridge->deleteLater();
|
||||||
|
|
||||||
// TODO: remove lights from this bridge (over GuhCore)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (device->deviceClassId() == hueLightDeviceClassId) {
|
if (device->deviceClassId() == hueLightDeviceClassId) {
|
||||||
@ -321,7 +319,6 @@ void DevicePluginPhilipsHue::networkManagerReplyReady(QNetworkReply *reply)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
processSetNameResponse(device, reply->readAll());
|
processSetNameResponse(device, reply->readAll());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
reply->deleteLater();
|
reply->deleteLater();
|
||||||
|
|||||||
@ -14,7 +14,7 @@
|
|||||||
"name": "Hue Bridge",
|
"name": "Hue Bridge",
|
||||||
"createMethods": ["discovery"],
|
"createMethods": ["discovery"],
|
||||||
"setupMethod": "pushButton",
|
"setupMethod": "pushButton",
|
||||||
"pairingInfo": "Please press within 30 seconds the button on the Hue Bridge before you continue",
|
"pairingInfo": "Please press the button on the Hue Bridge within 30 seconds before you continue",
|
||||||
"paramTypes": [
|
"paramTypes": [
|
||||||
{
|
{
|
||||||
"name": "name",
|
"name": "name",
|
||||||
|
|||||||
@ -180,11 +180,44 @@ QList<DeviceClass> GuhCore::supportedDevices(const VendorId &vendorId) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*! Removes a configured \l{Device} with the given \a deviceId and \a removePolicyList. */
|
/*! Removes a configured \l{Device} with the given \a deviceId and \a removePolicyList. */
|
||||||
DeviceManager::DeviceError GuhCore::removeConfiguredDevice(const DeviceId &deviceId, const QHash<RuleId, RuleEngine::RemovePolicy> &removePolicyList)
|
QPair<DeviceManager::DeviceError, QList<RuleId> > GuhCore::removeConfiguredDevice(const DeviceId &deviceId, const QHash<RuleId, RuleEngine::RemovePolicy> &removePolicyList)
|
||||||
{
|
{
|
||||||
|
// Check if this is a child device
|
||||||
|
Device *device = findConfiguredDevice(deviceId);
|
||||||
|
if (!device->parentId().isNull()) {
|
||||||
|
qCWarning(dcDeviceManager) << "The device is a child of" << device->parentId().toString() << ". Please remove the parent device.";
|
||||||
|
return QPair<DeviceManager::DeviceError, QList<RuleId> > (DeviceManager::DeviceErrorDeviceIsChild, QList<RuleId>());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if this device has child devices
|
||||||
|
QList<Device *> devicesToRemove;
|
||||||
|
devicesToRemove.append(device);
|
||||||
|
QList<Device *> childDevices = m_deviceManager->findChildDevices(device);
|
||||||
|
if (!childDevices.isEmpty()) {
|
||||||
|
foreach (Device *child, childDevices) {
|
||||||
|
devicesToRemove.append(child);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// check devices
|
||||||
|
QList<RuleId> offendingRules;
|
||||||
|
qCDebug(dcDeviceManager) << "Devices to remove:";
|
||||||
|
foreach (Device *d, devicesToRemove) {
|
||||||
|
qCDebug(dcDeviceManager) << " -> " << d->name() << d->id().toString();
|
||||||
|
|
||||||
|
// Check if device is in a rule
|
||||||
|
foreach (const RuleId &ruleId, m_ruleEngine->findRules(d->id())) {
|
||||||
|
qCDebug(dcDeviceManager) << " -> in rule:" << ruleId.toString();
|
||||||
|
if (!offendingRules.contains(ruleId)) {
|
||||||
|
offendingRules.append(ruleId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// check each offending rule if there is a corresponding remove policy
|
||||||
QHash<RuleId, RuleEngine::RemovePolicy> toBeChanged;
|
QHash<RuleId, RuleEngine::RemovePolicy> toBeChanged;
|
||||||
QList<RuleId> unhandledRules;
|
QList<RuleId> unhandledRules;
|
||||||
foreach (const RuleId &ruleId, m_ruleEngine->findRules(deviceId)) {
|
foreach (const RuleId &ruleId, offendingRules) {
|
||||||
bool found = false;
|
bool found = false;
|
||||||
foreach (const RuleId &policyRuleId, removePolicyList.keys()) {
|
foreach (const RuleId &policyRuleId, removePolicyList.keys()) {
|
||||||
if (ruleId == policyRuleId) {
|
if (ruleId == policyRuleId) {
|
||||||
@ -193,14 +226,14 @@ DeviceManager::DeviceError GuhCore::removeConfiguredDevice(const DeviceId &devic
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!found) {
|
if (!found)
|
||||||
unhandledRules.append(ruleId);
|
unhandledRules.append(ruleId);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!unhandledRules.isEmpty()) {
|
if (!unhandledRules.isEmpty()) {
|
||||||
qCWarning(dcDeviceManager) << "There are unhandled rules which depend on this device.";
|
qCWarning(dcDeviceManager) << "There are unhandled rules which depend on this device:\n" << unhandledRules;
|
||||||
return DeviceManager::DeviceErrorDeviceInUse;
|
return QPair<DeviceManager::DeviceError, QList<RuleId> > (DeviceManager::DeviceErrorDeviceInRule, unhandledRules);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the rules...
|
// Update the rules...
|
||||||
@ -208,13 +241,87 @@ DeviceManager::DeviceError GuhCore::removeConfiguredDevice(const DeviceId &devic
|
|||||||
if (toBeChanged.value(ruleId) == RuleEngine::RemovePolicyCascade) {
|
if (toBeChanged.value(ruleId) == RuleEngine::RemovePolicyCascade) {
|
||||||
m_ruleEngine->removeRule(ruleId);
|
m_ruleEngine->removeRule(ruleId);
|
||||||
} else if (toBeChanged.value(ruleId) == RuleEngine::RemovePolicyUpdate){
|
} else if (toBeChanged.value(ruleId) == RuleEngine::RemovePolicyUpdate){
|
||||||
m_ruleEngine->removeDeviceFromRule(ruleId, deviceId);
|
foreach (Device *d, devicesToRemove) {
|
||||||
|
m_ruleEngine->removeDeviceFromRule(ruleId, d->id());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// remove the child devices
|
||||||
|
foreach (Device *d, childDevices) {
|
||||||
|
DeviceManager::DeviceError removeError = m_deviceManager->removeConfiguredDevice(d->id());
|
||||||
|
if (removeError == DeviceManager::DeviceErrorNoError) {
|
||||||
|
m_logger->removeDeviceLogs(d->id());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// delete the devices
|
||||||
DeviceManager::DeviceError removeError = m_deviceManager->removeConfiguredDevice(deviceId);
|
DeviceManager::DeviceError removeError = m_deviceManager->removeConfiguredDevice(deviceId);
|
||||||
if (removeError == DeviceManager::DeviceErrorNoError)
|
if (removeError == DeviceManager::DeviceErrorNoError) {
|
||||||
m_logger->removeDeviceLogs(deviceId);
|
m_logger->removeDeviceLogs(deviceId);
|
||||||
|
}
|
||||||
|
|
||||||
|
return QPair<DeviceManager::DeviceError, QList<RuleId> > (DeviceManager::DeviceErrorNoError, QList<RuleId>());
|
||||||
|
}
|
||||||
|
|
||||||
|
DeviceManager::DeviceError GuhCore::removeConfiguredDevice(const DeviceId &deviceId, const RuleEngine::RemovePolicy &removePolicy)
|
||||||
|
{
|
||||||
|
// Check if this is a child device
|
||||||
|
Device *device = findConfiguredDevice(deviceId);
|
||||||
|
if (!device->parentId().isNull()) {
|
||||||
|
qCWarning(dcDeviceManager) << "The device is a child of" << device->parentId().toString() << ". Please remove the parent device.";
|
||||||
|
return DeviceManager::DeviceErrorDeviceIsChild;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if this device has child devices
|
||||||
|
QList<Device *> devicesToRemove;
|
||||||
|
devicesToRemove.append(device);
|
||||||
|
QList<Device *> childDevices = m_deviceManager->findChildDevices(device);
|
||||||
|
if (!childDevices.isEmpty()) {
|
||||||
|
foreach (Device *child, childDevices) {
|
||||||
|
devicesToRemove.append(child);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// check devices
|
||||||
|
QList<RuleId> offendingRules;
|
||||||
|
qCDebug(dcDeviceManager) << "Devices to remove:";
|
||||||
|
foreach (Device *d, devicesToRemove) {
|
||||||
|
qCDebug(dcDeviceManager) << " -> " << d->name() << d->id().toString();
|
||||||
|
|
||||||
|
// Check if device is in a rule
|
||||||
|
foreach (const RuleId &ruleId, m_ruleEngine->findRules(d->id())) {
|
||||||
|
qCDebug(dcDeviceManager) << " -> in rule:" << ruleId.toString();
|
||||||
|
if (!offendingRules.contains(ruleId)) {
|
||||||
|
offendingRules.append(ruleId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// apply removepolicy for foreach rule
|
||||||
|
foreach (const RuleId &ruleId, offendingRules) {
|
||||||
|
if (removePolicy == RuleEngine::RemovePolicyCascade) {
|
||||||
|
m_ruleEngine->removeRule(ruleId);
|
||||||
|
} else if (removePolicy == RuleEngine::RemovePolicyUpdate){
|
||||||
|
foreach (Device *d, devicesToRemove) {
|
||||||
|
m_ruleEngine->removeDeviceFromRule(ruleId, d->id());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove the child devices
|
||||||
|
foreach (Device *d, childDevices) {
|
||||||
|
DeviceManager::DeviceError removeError = m_deviceManager->removeConfiguredDevice(d->id());
|
||||||
|
if (removeError == DeviceManager::DeviceErrorNoError) {
|
||||||
|
m_logger->removeDeviceLogs(d->id());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// delete the devices
|
||||||
|
DeviceManager::DeviceError removeError = m_deviceManager->removeConfiguredDevice(deviceId);
|
||||||
|
if (removeError == DeviceManager::DeviceErrorNoError) {
|
||||||
|
m_logger->removeDeviceLogs(deviceId);
|
||||||
|
}
|
||||||
|
|
||||||
return removeError;
|
return removeError;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -70,12 +70,13 @@ public:
|
|||||||
DeviceManager::DeviceError discoverDevices(const DeviceClassId &deviceClassId, const ParamList ¶ms);
|
DeviceManager::DeviceError discoverDevices(const DeviceClassId &deviceClassId, const ParamList ¶ms);
|
||||||
DeviceManager::DeviceError addConfiguredDevice(const DeviceClassId &deviceClassId, const ParamList ¶ms, const DeviceId &newId);
|
DeviceManager::DeviceError addConfiguredDevice(const DeviceClassId &deviceClassId, const ParamList ¶ms, const DeviceId &newId);
|
||||||
DeviceManager::DeviceError addConfiguredDevice(const DeviceClassId &deviceClassId, const DeviceDescriptorId &deviceDescriptorId, const DeviceId &newId);
|
DeviceManager::DeviceError addConfiguredDevice(const DeviceClassId &deviceClassId, const DeviceDescriptorId &deviceDescriptorId, const DeviceId &newId);
|
||||||
QList<Device*> configuredDevices() const;
|
QList<Device *> configuredDevices() const;
|
||||||
Device *findConfiguredDevice(const DeviceId &deviceId) const;
|
Device *findConfiguredDevice(const DeviceId &deviceId) const;
|
||||||
QList<Device*> findConfiguredDevices(const DeviceClassId &deviceClassId) const;
|
QList<Device *> findConfiguredDevices(const DeviceClassId &deviceClassId) const;
|
||||||
DeviceManager::DeviceError editDevice(const DeviceId &deviceId, const ParamList ¶ms);
|
DeviceManager::DeviceError editDevice(const DeviceId &deviceId, const ParamList ¶ms);
|
||||||
DeviceManager::DeviceError editDevice(const DeviceId &deviceId, const DeviceDescriptorId &deviceDescriptorId);
|
DeviceManager::DeviceError editDevice(const DeviceId &deviceId, const DeviceDescriptorId &deviceDescriptorId);
|
||||||
DeviceManager::DeviceError removeConfiguredDevice(const DeviceId &deviceId, const QHash<RuleId, RuleEngine::RemovePolicy> &removePolicyList);
|
QPair<DeviceManager::DeviceError, QList<RuleId> >removeConfiguredDevice(const DeviceId &deviceId, const QHash<RuleId, RuleEngine::RemovePolicy> &removePolicyList);
|
||||||
|
DeviceManager::DeviceError removeConfiguredDevice(const DeviceId &deviceId, const RuleEngine::RemovePolicy &removePolicy);
|
||||||
|
|
||||||
DeviceManager::DeviceError pairDevice(const PairingTransactionId &pairingTransactionId, const DeviceClassId &deviceClassId, const DeviceDescriptorId &deviceDescriptorId);
|
DeviceManager::DeviceError pairDevice(const PairingTransactionId &pairingTransactionId, const DeviceClassId &deviceClassId, const DeviceDescriptorId &deviceDescriptorId);
|
||||||
DeviceManager::DeviceError pairDevice(const PairingTransactionId &pairingTransactionId, const DeviceClassId &deviceClassId, const ParamList ¶ms);
|
DeviceManager::DeviceError pairDevice(const PairingTransactionId &pairingTransactionId, const DeviceClassId &deviceClassId, const ParamList ¶ms);
|
||||||
@ -120,7 +121,6 @@ signals:
|
|||||||
void ruleActiveChanged(const Rule &rule);
|
void ruleActiveChanged(const Rule &rule);
|
||||||
void ruleConfigurationChanged(const Rule &rule);
|
void ruleConfigurationChanged(const Rule &rule);
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
RuleEngine *ruleEngine() const;
|
RuleEngine *ruleEngine() const;
|
||||||
|
|
||||||
|
|||||||
@ -113,13 +113,13 @@ DeviceHandler::DeviceHandler(QObject *parent) :
|
|||||||
|
|
||||||
returns.clear(); // Reused params from above!
|
returns.clear(); // Reused params from above!
|
||||||
setDescription("PairDevice", "Pair a device. "
|
setDescription("PairDevice", "Pair a device. "
|
||||||
"Use this for DeviceClasses with a setupMethod different than SetupMethodJustAdd."
|
"Use this for DeviceClasses with a setupMethod different than SetupMethodJustAdd. "
|
||||||
"Use deviceDescriptorId or deviceParams, depending on the createMethod of the device class. "
|
"Use deviceDescriptorId or deviceParams, depending on the createMethod of the device class. "
|
||||||
"CreateMethodJustAdd takes the parameters you want to have with that device. "
|
"CreateMethodJustAdd takes the parameters you want to have with that device. "
|
||||||
"CreateMethodDiscovery requires the use of a deviceDescriptorId. "
|
"CreateMethodDiscovery requires the use of a deviceDescriptorId. "
|
||||||
"If success is true, the return values will contain a pairingTransactionId, a displayMessage and "
|
"If success is true, the return values will contain a pairingTransactionId, a displayMessage and "
|
||||||
"the setupMethod. Depending on the setupMethod you should either proceed with AddConfiguredDevice "
|
"the setupMethod. Depending on the setupMethod you should either proceed with AddConfiguredDevice "
|
||||||
" or PairDevice."
|
"or PairDevice."
|
||||||
);
|
);
|
||||||
setParams("PairDevice", params);
|
setParams("PairDevice", params);
|
||||||
returns.insert("deviceError", JsonTypes::deviceErrorRef());
|
returns.insert("deviceError", JsonTypes::deviceErrorRef());
|
||||||
@ -181,9 +181,11 @@ DeviceHandler::DeviceHandler(QObject *parent) :
|
|||||||
policy.insert("ruleId", JsonTypes::basicTypeToString(JsonTypes::Uuid));
|
policy.insert("ruleId", JsonTypes::basicTypeToString(JsonTypes::Uuid));
|
||||||
policy.insert("policy", JsonTypes::removePolicyRef());
|
policy.insert("policy", JsonTypes::removePolicyRef());
|
||||||
removePolicyList.append(policy);
|
removePolicyList.append(policy);
|
||||||
|
params.insert("o:removePolicy", JsonTypes::removePolicyRef());
|
||||||
params.insert("o:removePolicyList", removePolicyList);
|
params.insert("o:removePolicyList", removePolicyList);
|
||||||
setParams("RemoveConfiguredDevice", params);
|
setParams("RemoveConfiguredDevice", params);
|
||||||
returns.insert("deviceError", JsonTypes::deviceErrorRef());
|
returns.insert("deviceError", JsonTypes::deviceErrorRef());
|
||||||
|
returns.insert("o:ruleIds", QVariantList() << JsonTypes::basicTypeToString(JsonTypes::Uuid));
|
||||||
setReturns("RemoveConfiguredDevice", returns);
|
setReturns("RemoveConfiguredDevice", returns);
|
||||||
|
|
||||||
params.clear(); returns.clear();
|
params.clear(); returns.clear();
|
||||||
@ -459,7 +461,17 @@ JsonReply *DeviceHandler::EditDevice(const QVariantMap ¶ms)
|
|||||||
|
|
||||||
JsonReply* DeviceHandler::RemoveConfiguredDevice(const QVariantMap ¶ms)
|
JsonReply* DeviceHandler::RemoveConfiguredDevice(const QVariantMap ¶ms)
|
||||||
{
|
{
|
||||||
|
QVariantMap returns;
|
||||||
DeviceId deviceId = DeviceId(params.value("deviceId").toString());
|
DeviceId deviceId = DeviceId(params.value("deviceId").toString());
|
||||||
|
|
||||||
|
// global removePolicy has priority
|
||||||
|
if (params.contains("removePolicy")) {
|
||||||
|
RuleEngine::RemovePolicy removePolicy = params.value("removePolicy").toString() == "RemovePolicyCascade" ? RuleEngine::RemovePolicyCascade : RuleEngine::RemovePolicyUpdate;
|
||||||
|
DeviceManager::DeviceError status = GuhCore::instance()->removeConfiguredDevice(deviceId, removePolicy);
|
||||||
|
returns.insert("deviceError", JsonTypes::deviceErrorToString(status));
|
||||||
|
return createReply(returns);
|
||||||
|
}
|
||||||
|
|
||||||
QHash<RuleId, RuleEngine::RemovePolicy> removePolicyList;
|
QHash<RuleId, RuleEngine::RemovePolicy> removePolicyList;
|
||||||
foreach (const QVariant &variant, params.value("removePolicyList").toList()) {
|
foreach (const QVariant &variant, params.value("removePolicyList").toList()) {
|
||||||
RuleId ruleId = RuleId(variant.toMap().value("ruleId").toString());
|
RuleId ruleId = RuleId(variant.toMap().value("ruleId").toString());
|
||||||
@ -467,9 +479,17 @@ JsonReply* DeviceHandler::RemoveConfiguredDevice(const QVariantMap ¶ms)
|
|||||||
removePolicyList.insert(ruleId, policy);
|
removePolicyList.insert(ruleId, policy);
|
||||||
}
|
}
|
||||||
|
|
||||||
QVariantMap returns;
|
QPair<DeviceManager::DeviceError, QList<RuleId> > status = GuhCore::instance()->removeConfiguredDevice(deviceId, removePolicyList);
|
||||||
DeviceManager::DeviceError status = GuhCore::instance()->removeConfiguredDevice(deviceId, removePolicyList);
|
returns.insert("deviceError", JsonTypes::deviceErrorToString(status.first));
|
||||||
returns.insert("deviceError", JsonTypes::deviceErrorToString(status));
|
|
||||||
|
if (!status.second.isEmpty()) {
|
||||||
|
QVariantList ruleIdList;
|
||||||
|
foreach (const RuleId &ruleId, status.second) {
|
||||||
|
ruleIdList.append(ruleId.toString());
|
||||||
|
}
|
||||||
|
returns.insert("ruleIds", ruleIdList);
|
||||||
|
}
|
||||||
|
|
||||||
return createReply(returns);
|
return createReply(returns);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -614,7 +634,6 @@ void DeviceHandler::deviceSetupFinished(Device *device, DeviceManager::DeviceErr
|
|||||||
}
|
}
|
||||||
reply->setData(returns);
|
reply->setData(returns);
|
||||||
reply->finished();
|
reply->finished();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DeviceHandler::deviceEditFinished(Device *device, DeviceManager::DeviceError status)
|
void DeviceHandler::deviceEditFinished(Device *device, DeviceManager::DeviceError status)
|
||||||
|
|||||||
@ -199,6 +199,7 @@ void JsonTypes::init()
|
|||||||
s_device.insert("name", basicTypeToString(String));
|
s_device.insert("name", basicTypeToString(String));
|
||||||
s_device.insert("params", QVariantList() << paramRef());
|
s_device.insert("params", QVariantList() << paramRef());
|
||||||
s_device.insert("setupComplete", basicTypeToString(Bool));
|
s_device.insert("setupComplete", basicTypeToString(Bool));
|
||||||
|
s_device.insert("o:parentId", basicTypeToString(Uuid));
|
||||||
|
|
||||||
// DeviceDescription
|
// DeviceDescription
|
||||||
s_deviceDescriptor.insert("id", basicTypeToString(Uuid));
|
s_deviceDescriptor.insert("id", basicTypeToString(Uuid));
|
||||||
@ -561,6 +562,10 @@ QVariantMap JsonTypes::packDevice(Device *device)
|
|||||||
foreach (const Param ¶m, device->params()) {
|
foreach (const Param ¶m, device->params()) {
|
||||||
params.append(packParam(param));
|
params.append(packParam(param));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!device->parentId().isNull())
|
||||||
|
variant.insert("parentId", device->parentId());
|
||||||
|
|
||||||
variant.insert("params", params);
|
variant.insert("params", params);
|
||||||
variant.insert("setupComplete", device->setupComplete());
|
variant.insert("setupComplete", device->setupComplete());
|
||||||
return variant;
|
return variant;
|
||||||
|
|||||||
@ -155,10 +155,19 @@ HttpReply *DevicesResource::proccessDeleteRequest(const HttpRequest &request, co
|
|||||||
return createErrorReply(HttpReply::BadRequest);
|
return createErrorReply(HttpReply::BadRequest);
|
||||||
|
|
||||||
// DELETE /api/v1/devices/{deviceId}
|
// DELETE /api/v1/devices/{deviceId}
|
||||||
if (urlTokens.count() == 4)
|
if (urlTokens.count() == 4) {
|
||||||
return removeDevice(m_device);
|
QVariantMap params;
|
||||||
|
if (request.urlQuery().hasQueryItem("params")) {
|
||||||
|
QString paramMapString = request.urlQuery().queryItemValue("params");
|
||||||
|
|
||||||
// TODO: /api/v1/devices/{deviceId}?ruleId={ruleId}&removePolicy={RemovePolicy}
|
QPair<bool, QVariant> verification = verifyPayload(paramMapString.toUtf8());
|
||||||
|
if (!verification.first)
|
||||||
|
return createErrorReply(HttpReply::BadRequest);
|
||||||
|
|
||||||
|
params = verification.second.toMap();
|
||||||
|
}
|
||||||
|
return removeDevice(m_device, params);
|
||||||
|
}
|
||||||
|
|
||||||
return createErrorReply(HttpReply::NotImplemented);
|
return createErrorReply(HttpReply::NotImplemented);
|
||||||
}
|
}
|
||||||
@ -232,19 +241,8 @@ HttpReply *DevicesResource::getConfiguredDevices() const
|
|||||||
{
|
{
|
||||||
qCDebug(dcRest) << "Get all configured devices";
|
qCDebug(dcRest) << "Get all configured devices";
|
||||||
HttpReply *reply = createSuccessReply();
|
HttpReply *reply = createSuccessReply();
|
||||||
QVariantList devices = JsonTypes::packConfiguredDevices();
|
|
||||||
|
|
||||||
QVariantList finalDevices;
|
|
||||||
foreach (const QVariant &deviceVariant, devices) {
|
|
||||||
QVariantMap deviceMap = deviceVariant.toMap();
|
|
||||||
Device* device = GuhCore::instance()->findConfiguredDevice(DeviceId(deviceMap.value("id").toString()));
|
|
||||||
QVariantList deviceStates = JsonTypes::packDeviceStates(device);
|
|
||||||
deviceMap.insert("states", deviceStates);
|
|
||||||
finalDevices.append(deviceMap);
|
|
||||||
}
|
|
||||||
|
|
||||||
reply->setHeader(HttpReply::ContentTypeHeader, "application/json; charset=\"utf-8\";");
|
reply->setHeader(HttpReply::ContentTypeHeader, "application/json; charset=\"utf-8\";");
|
||||||
reply->setPayload(QJsonDocument::fromVariant(finalDevices).toJson());
|
reply->setPayload(QJsonDocument::fromVariant(JsonTypes::packConfiguredDevices()).toJson());
|
||||||
return reply;
|
return reply;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -252,14 +250,8 @@ HttpReply *DevicesResource::getConfiguredDevice(Device *device) const
|
|||||||
{
|
{
|
||||||
qCDebug(dcRest) << "Get configured device with id:" << device->id().toString();
|
qCDebug(dcRest) << "Get configured device with id:" << device->id().toString();
|
||||||
HttpReply *reply = createSuccessReply();
|
HttpReply *reply = createSuccessReply();
|
||||||
QVariantMap deviceMap = JsonTypes::packDevice(device);
|
|
||||||
QVariantList deviceStates = JsonTypes::packDeviceStates(device);
|
|
||||||
deviceMap.insert("states", deviceStates);
|
|
||||||
|
|
||||||
qCDebug(dcRest) << deviceMap;
|
|
||||||
|
|
||||||
reply->setHeader(HttpReply::ContentTypeHeader, "application/json; charset=\"utf-8\";");
|
reply->setHeader(HttpReply::ContentTypeHeader, "application/json; charset=\"utf-8\";");
|
||||||
reply->setPayload(QJsonDocument::fromVariant(deviceMap).toJson());
|
reply->setPayload(QJsonDocument::fromVariant(JsonTypes::packDevice(device)).toJson());
|
||||||
return reply;
|
return reply;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -283,18 +275,49 @@ HttpReply *DevicesResource::getDeviceStateValue(Device *device, const StateTypeI
|
|||||||
return reply;
|
return reply;
|
||||||
}
|
}
|
||||||
|
|
||||||
HttpReply *DevicesResource::removeDevice(Device *device) const
|
HttpReply *DevicesResource::removeDevice(Device *device, const QVariantMap ¶ms) const
|
||||||
{
|
{
|
||||||
qCDebug(dcRest) << "Remove device with id:" << device->id().toString();
|
qCDebug(dcRest) << "Remove device with id:" << device->id().toString();
|
||||||
DeviceManager::DeviceError result = GuhCore::instance()->removeConfiguredDevice(device->id(), QHash<RuleId, RuleEngine::RemovePolicy>());
|
qCDebug(dcRest) << QJsonDocument::fromVariant(params).toJson();
|
||||||
|
|
||||||
// TODO: /api/v1/devices/{deviceId}?ruleId={ruleId}&removePolicy={RemovePolicy}
|
// global removePolicy has priority
|
||||||
|
if (params.contains("removePolicy")) {
|
||||||
|
RuleEngine::RemovePolicy removePolicy = params.value("removePolicy").toString() == "RemovePolicyCascade" ? RuleEngine::RemovePolicyCascade : RuleEngine::RemovePolicyUpdate;
|
||||||
|
DeviceManager::DeviceError result = GuhCore::instance()->removeConfiguredDevice(device->id(), removePolicy);
|
||||||
|
return createDeviceErrorReply(HttpReply::Ok, result);
|
||||||
|
}
|
||||||
|
|
||||||
if (result == DeviceManager::DeviceErrorNoError) {
|
QHash<RuleId, RuleEngine::RemovePolicy> removePolicyList;
|
||||||
HttpReply *reply = createDeviceErrorReply(HttpReply::Ok, result);
|
foreach (const QVariant &variant, params.value("removePolicyList").toList()) {
|
||||||
|
RuleId ruleId = RuleId(variant.toMap().value("ruleId").toString());
|
||||||
|
RuleEngine::RemovePolicy policy = variant.toMap().value("policy").toString() == "RemovePolicyCascade" ? RuleEngine::RemovePolicyCascade : RuleEngine::RemovePolicyUpdate;
|
||||||
|
removePolicyList.insert(ruleId, policy);
|
||||||
|
}
|
||||||
|
|
||||||
|
QPair<DeviceManager::DeviceError, QList<RuleId> > status = GuhCore::instance()->removeConfiguredDevice(device->id(), removePolicyList);
|
||||||
|
|
||||||
|
// if there are offending rules
|
||||||
|
if (!status.second.isEmpty()) {
|
||||||
|
QVariantList ruleIdList;
|
||||||
|
QVariantMap returns;
|
||||||
|
returns.insert("deviceError", JsonTypes::deviceErrorToString(status.first));
|
||||||
|
|
||||||
|
foreach (const RuleId &ruleId, status.second) {
|
||||||
|
ruleIdList.append(ruleId.toString());
|
||||||
|
}
|
||||||
|
returns.insert("ruleIds", ruleIdList);
|
||||||
|
|
||||||
|
HttpReply *reply = createErrorReply(HttpReply::BadRequest);
|
||||||
|
reply->setHeader(HttpReply::ContentTypeHeader, "application/json; charset=\"utf-8\";");
|
||||||
|
reply->setPayload(QJsonDocument::fromVariant(returns).toJson());
|
||||||
return reply;
|
return reply;
|
||||||
}
|
}
|
||||||
return createDeviceErrorReply(HttpReply::BadRequest, result);
|
|
||||||
|
if (status.first == DeviceManager::DeviceErrorNoError)
|
||||||
|
return createDeviceErrorReply(HttpReply::Ok, status.first);
|
||||||
|
|
||||||
|
return createDeviceErrorReply(HttpReply::BadRequest, status.first);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
HttpReply *DevicesResource::executeAction(Device *device, const ActionTypeId &actionTypeId, const QByteArray &payload) const
|
HttpReply *DevicesResource::executeAction(Device *device, const ActionTypeId &actionTypeId, const QByteArray &payload) const
|
||||||
|
|||||||
@ -64,7 +64,7 @@ private:
|
|||||||
HttpReply *getDeviceStateValue(Device *device, const StateTypeId &stateTypeId) const;
|
HttpReply *getDeviceStateValue(Device *device, const StateTypeId &stateTypeId) const;
|
||||||
|
|
||||||
// Delete methods
|
// Delete methods
|
||||||
HttpReply *removeDevice(Device *device) const;
|
HttpReply *removeDevice(Device *device, const QVariantMap ¶ms) const;
|
||||||
|
|
||||||
// Post methods
|
// Post methods
|
||||||
HttpReply *executeAction(Device *device, const ActionTypeId &actionTypeId, const QByteArray &payload) const;
|
HttpReply *executeAction(Device *device, const ActionTypeId &actionTypeId, const QByteArray &payload) const;
|
||||||
|
|||||||
@ -551,9 +551,10 @@ QList<RuleId> RuleEngine::findRules(const DeviceId &deviceId)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!offending && rule.stateEvaluator().containsDevice(deviceId)) {
|
|
||||||
|
if (!offending && rule.stateEvaluator().containsDevice(deviceId))
|
||||||
offending = true;
|
offending = true;
|
||||||
}
|
|
||||||
if (!offending) {
|
if (!offending) {
|
||||||
foreach (const RuleAction &action, rule.actions()) {
|
foreach (const RuleAction &action, rule.actions()) {
|
||||||
if (action.deviceId() == deviceId) {
|
if (action.deviceId() == deviceId) {
|
||||||
@ -562,9 +563,19 @@ QList<RuleId> RuleEngine::findRules(const DeviceId &deviceId)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (offending) {
|
|
||||||
offendingRules.append(rule.id());
|
if (!offending) {
|
||||||
|
foreach (const RuleAction &action, rule.exitActions()) {
|
||||||
|
if (action.deviceId() == deviceId) {
|
||||||
|
offending = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (offending)
|
||||||
|
offendingRules.append(rule.id());
|
||||||
|
|
||||||
}
|
}
|
||||||
return offendingRules;
|
return offendingRules;
|
||||||
}
|
}
|
||||||
@ -572,10 +583,12 @@ QList<RuleId> RuleEngine::findRules(const DeviceId &deviceId)
|
|||||||
/*! Removes a \l{Device} from a \l{Rule} with the given \a id and \a deviceId. */
|
/*! Removes a \l{Device} from a \l{Rule} with the given \a id and \a deviceId. */
|
||||||
void RuleEngine::removeDeviceFromRule(const RuleId &id, const DeviceId &deviceId)
|
void RuleEngine::removeDeviceFromRule(const RuleId &id, const DeviceId &deviceId)
|
||||||
{
|
{
|
||||||
if (!m_rules.contains(id)) {
|
if (!m_rules.contains(id))
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
Rule rule = m_rules.value(id);
|
Rule rule = m_rules.value(id);
|
||||||
|
|
||||||
|
// remove device from eventDescriptors
|
||||||
QList<EventDescriptor> eventDescriptors = rule.eventDescriptors();
|
QList<EventDescriptor> eventDescriptors = rule.eventDescriptors();
|
||||||
QList<int> removeIndexes;
|
QList<int> removeIndexes;
|
||||||
for (int i = 0; i < eventDescriptors.count(); i++) {
|
for (int i = 0; i < eventDescriptors.count(); i++) {
|
||||||
@ -586,9 +599,12 @@ void RuleEngine::removeDeviceFromRule(const RuleId &id, const DeviceId &deviceId
|
|||||||
while (removeIndexes.count() > 0) {
|
while (removeIndexes.count() > 0) {
|
||||||
eventDescriptors.takeAt(removeIndexes.takeLast());
|
eventDescriptors.takeAt(removeIndexes.takeLast());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// remove device from state evaluators
|
||||||
StateEvaluator stateEvalatuator = rule.stateEvaluator();
|
StateEvaluator stateEvalatuator = rule.stateEvaluator();
|
||||||
stateEvalatuator.removeDevice(deviceId);
|
stateEvalatuator.removeDevice(deviceId);
|
||||||
|
|
||||||
|
// remove device from actions
|
||||||
QList<RuleAction> actions = rule.actions();
|
QList<RuleAction> actions = rule.actions();
|
||||||
for (int i = 0; i < actions.count(); i++) {
|
for (int i = 0; i < actions.count(); i++) {
|
||||||
if (actions.at(i).deviceId() == deviceId) {
|
if (actions.at(i).deviceId() == deviceId) {
|
||||||
@ -598,8 +614,30 @@ void RuleEngine::removeDeviceFromRule(const RuleId &id, const DeviceId &deviceId
|
|||||||
while (removeIndexes.count() > 0) {
|
while (removeIndexes.count() > 0) {
|
||||||
actions.takeAt(removeIndexes.takeLast());
|
actions.takeAt(removeIndexes.takeLast());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// remove device from exit actions
|
||||||
|
QList<RuleAction> exitActions = rule.exitActions();
|
||||||
|
for (int i = 0; i < exitActions.count(); i++) {
|
||||||
|
if (exitActions.at(i).deviceId() == deviceId) {
|
||||||
|
removeIndexes.append(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (removeIndexes.count() > 0) {
|
||||||
|
exitActions.takeAt(removeIndexes.takeLast());
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove the rule from settings
|
||||||
|
GuhSettings settings(GuhSettings::SettingsRoleRules);
|
||||||
|
settings.beginGroup(id.toString());
|
||||||
|
settings.remove("");
|
||||||
|
settings.endGroup();
|
||||||
|
|
||||||
Rule newRule(id, rule.name(), eventDescriptors, stateEvalatuator, actions);
|
Rule newRule(id, rule.name(), eventDescriptors, stateEvalatuator, actions);
|
||||||
m_rules[id] = newRule;
|
m_rules[id] = newRule;
|
||||||
|
|
||||||
|
// save it
|
||||||
|
saveRule(newRule);
|
||||||
|
emit ruleConfigurationChanged(newRule);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RuleEngine::containsEvent(const Rule &rule, const Event &event)
|
bool RuleEngine::containsEvent(const Rule &rule, const Event &event)
|
||||||
|
|||||||
Reference in New Issue
Block a user