add createmethod and setupmethod params

add support for createmethod "auto"
add functional boblight plugin
This commit is contained in:
Michael Zanetti 2014-04-13 10:27:08 +02:00
parent 9b4c28801c
commit 8d1c7f9c03
36 changed files with 686 additions and 72 deletions

View File

@ -100,6 +100,7 @@ DeviceManager::DeviceManager(QObject *parent) :
// 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);
QMetaObject::invokeMethod(this, "createNewAutoDevices", Qt::QueuedConnection);
// Make sure this is always emitted after plugins and devices are loaded // Make sure this is always emitted after plugins and devices are loaded
QMetaObject::invokeMethod(this, "loaded", Qt::QueuedConnection); QMetaObject::invokeMethod(this, "loaded", Qt::QueuedConnection);
} }
@ -111,11 +112,20 @@ QList<DevicePlugin *> DeviceManager::plugins() const
} }
/*! Returns the \{DevicePlugin} with the given \a id. Null if the id couldn't be found. */ /*! Returns the \{DevicePlugin} with the given \a id. Null if the id couldn't be found. */
DevicePlugin *DeviceManager::plugin(const QUuid &id) const DevicePlugin *DeviceManager::plugin(const PluginId &id) const
{ {
return m_devicePlugins.value(id); return m_devicePlugins.value(id);
} }
void DeviceManager::setPluginConfig(const PluginId &pluginId, const QVariantMap &pluginConfig)
{
DevicePlugin *plugin = m_devicePlugins.value(pluginId);
plugin->setConfiguration(pluginConfig);
QSettings settings;
settings.setValue(plugin->pluginId().toString(), pluginConfig);
createNewAutoDevices();
}
QList<Vendor> DeviceManager::supportedVendors() const QList<Vendor> DeviceManager::supportedVendors() const
{ {
return m_supportedVendors.values(); return m_supportedVendors.values();
@ -142,6 +152,19 @@ QList<DeviceClass> DeviceManager::supportedDevices(const VendorId &vendorId) con
be generated. be generated.
*/ */
DeviceManager::DeviceError DeviceManager::addConfiguredDevice(const DeviceClassId &deviceClassId, const QVariantMap &params, const DeviceId id) DeviceManager::DeviceError DeviceManager::addConfiguredDevice(const DeviceClassId &deviceClassId, const QVariantMap &params, const DeviceId id)
{
DeviceClass deviceClass = findDeviceClass(deviceClassId);
if (deviceClass.id().isNull()) {
qWarning() << "cannot find a device class with id" << deviceClassId;
return DeviceErrorDeviceClassNotFound;
}
if (deviceClass.createMethod() == DeviceClass::CreateMethodUser) {
return addConfiguredDeviceInternal(deviceClassId, params, id);
}
return DeviceErrorCreationNotSupported;
}
DeviceManager::DeviceError DeviceManager::addConfiguredDeviceInternal(const DeviceClassId &deviceClassId, const QVariantMap &params, const DeviceId id)
{ {
DeviceClass deviceClass = findDeviceClass(deviceClassId); DeviceClass deviceClass = findDeviceClass(deviceClassId);
if (deviceClass.id().isNull()) { if (deviceClass.id().isNull()) {
@ -182,7 +205,7 @@ DeviceManager::DeviceError DeviceManager::addConfiguredDevice(const DeviceClassI
return DeviceErrorNoError; return DeviceErrorNoError;
} }
DeviceManager::DeviceError DeviceManager::removeConfiguredDevice(const QUuid &deviceId) DeviceManager::DeviceError DeviceManager::removeConfiguredDevice(const DeviceId &deviceId)
{ {
Device *device = findConfiguredDevice(deviceId); Device *device = findConfiguredDevice(deviceId);
if (!device) { if (!device) {
@ -207,7 +230,7 @@ DeviceManager::DeviceError DeviceManager::removeConfiguredDevice(const QUuid &de
} }
/*! Returns the \l{Device} with the given \a id. Null if the id couldn't be found. */ /*! Returns the \l{Device} with the given \a id. Null if the id couldn't be found. */
Device *DeviceManager::findConfiguredDevice(const QUuid &id) const Device *DeviceManager::findConfiguredDevice(const DeviceId &id) const
{ {
foreach (Device *device, m_configuredDevices) { foreach (Device *device, m_configuredDevices) {
if (device->id() == id) { if (device->id() == id) {
@ -224,7 +247,7 @@ QList<Device *> DeviceManager::configuredDevices() const
} }
/*! Returns all \l{Device}{Devices} matching the \l{DeviceClass} referred by \a deviceClassId. */ /*! Returns all \l{Device}{Devices} matching the \l{DeviceClass} referred by \a deviceClassId. */
QList<Device *> DeviceManager::findConfiguredDevices(const QUuid &deviceClassId) const QList<Device *> DeviceManager::findConfiguredDevices(const DeviceClassId &deviceClassId) const
{ {
QList<Device*> ret; QList<Device*> ret;
foreach (Device *device, m_configuredDevices) { foreach (Device *device, m_configuredDevices) {
@ -235,19 +258,6 @@ QList<Device *> DeviceManager::findConfiguredDevices(const QUuid &deviceClassId)
return ret; return ret;
} }
/*! For conveninece, this returns the \{DeviceClass} that describes the \l{EventType} referred by \a eventTypeId. */
DeviceClass DeviceManager::findDeviceClassforEvent(const QUuid &eventTypeId) const
{
foreach (const DeviceClass &deviceClass, m_supportedDevices) {
foreach (const EventType &eventType, deviceClass.events()) {
if (eventType.id() == eventTypeId) {
return deviceClass;
}
}
}
return DeviceClass();
}
/*! For conveninece, this returns the \{DeviceClass} with the id given by \a deviceClassId. /*! For conveninece, this returns the \{DeviceClass} with the id given by \a deviceClassId.
Note: The returned DeviceClass may be invalid.*/ Note: The returned DeviceClass may be invalid.*/
DeviceClass DeviceManager::findDeviceClass(const QUuid &deviceClassId) const DeviceClass DeviceManager::findDeviceClass(const QUuid &deviceClassId) const
@ -275,14 +285,19 @@ DeviceManager::DeviceError DeviceManager::executeAction(const Action &action)
foreach (const ActionType &actionType, deviceClass.actions()) { foreach (const ActionType &actionType, deviceClass.actions()) {
if (actionType.id() == action.actionTypeId()) { if (actionType.id() == action.actionTypeId()) {
found = true; found = true;
if (actionType.parameters().count() > action.params().count()) {
return DeviceErrorMissingParameter;
}
continue;
} }
} }
if (!found) { if (!found) {
return DeviceErrorActionTypeNotFound; return DeviceErrorActionTypeNotFound;
} }
m_devicePlugins.value(device->pluginId())->executeAction(device, action); return m_devicePlugins.value(device->pluginId())->executeAction(device, action);
return DeviceErrorNoError;
} }
} }
return DeviceErrorDeviceNotFound; return DeviceErrorDeviceNotFound;
@ -313,6 +328,11 @@ void DeviceManager::loadPlugins()
m_supportedDevices.insert(deviceClass.id(), deviceClass); m_supportedDevices.insert(deviceClass.id(), deviceClass);
qDebug() << "* Loaded device class:" << deviceClass.name(); qDebug() << "* Loaded device class:" << deviceClass.name();
} }
QSettings settings;
if (settings.contains(pluginIface->pluginId().toString())) {
pluginIface->setConfiguration(settings.value(pluginIface->pluginId().toString()).toMap());
}
m_devicePlugins.insert(pluginIface->pluginId(), pluginIface); m_devicePlugins.insert(pluginIface->pluginId(), pluginIface);
connect(pluginIface, &DevicePlugin::emitEvent, this, &DeviceManager::emitEvent); connect(pluginIface, &DevicePlugin::emitEvent, this, &DeviceManager::emitEvent);
} }
@ -350,6 +370,35 @@ void DeviceManager::storeConfiguredDevices()
} }
} }
void DeviceManager::createNewAutoDevices()
{
bool haveNewDevice = false;
foreach (const DeviceClass &deviceClass, m_supportedDevices) {
if (deviceClass.createMethod() != DeviceClass::CreateMethodAuto) {
continue;
}
qDebug() << "found auto device class" << deviceClass.name();
DevicePlugin *plugin = m_devicePlugins.value(deviceClass.pluginId());
bool success = false;
do {
QList<Device*> loadedDevices = findConfiguredDevices(deviceClass.id());
Device *device = new Device(plugin->pluginId(), DeviceId::createDeviceId(), deviceClass.id());
success = plugin->configureAutoDevice(loadedDevices, device);
if (success) {
qDebug() << "New device detected for" << deviceClass.name() << device->name();
setupDevice(device);
m_configuredDevices.append(device);
haveNewDevice = true;
} else {
qDebug() << "No newly detected devices for" << deviceClass.name();
delete device;
}
} while (success);
}
storeConfiguredDevices();
}
void DeviceManager::slotDeviceStateValueChanged(const QUuid &stateTypeId, const QVariant &value) void DeviceManager::slotDeviceStateValueChanged(const QUuid &stateTypeId, const QVariant &value)
{ {
Device *device = qobject_cast<Device*>(sender()); Device *device = qobject_cast<Device*>(sender());

View File

@ -53,23 +53,27 @@ public:
DeviceErrorMissingParameter, DeviceErrorMissingParameter,
DeviceErrorPluginNotFound, DeviceErrorPluginNotFound,
DeviceErrorSetupFailed, DeviceErrorSetupFailed,
DeviceErrorDuplicateUuid DeviceErrorDuplicateUuid,
DeviceErrorCreationNotSupported,
DeviceErrorDeviceParameterError,
DeviceErrorActionParameterError
}; };
explicit DeviceManager(QObject *parent = 0); explicit DeviceManager(QObject *parent = 0);
QList<DevicePlugin*> plugins() const; QList<DevicePlugin*> plugins() const;
DevicePlugin* plugin(const QUuid &id) const; DevicePlugin* plugin(const PluginId &id) const;
void setPluginConfig(const PluginId &pluginId, const QVariantMap &pluginConfig);
QList<Vendor> supportedVendors() const; QList<Vendor> supportedVendors() const;
QList<DeviceClass> supportedDevices(const VendorId &vendorId = VendorId()) const; QList<DeviceClass> supportedDevices(const VendorId &vendorId = VendorId()) const;
QList<Device*> configuredDevices() const; QList<Device*> configuredDevices() const;
DeviceError addConfiguredDevice(const DeviceClassId &deviceClassId, const QVariantMap &params, const DeviceId id = DeviceId::createDeviceId()); DeviceError addConfiguredDevice(const DeviceClassId &deviceClassId, const QVariantMap &params, const DeviceId id = DeviceId::createDeviceId());
DeviceError removeConfiguredDevice(const QUuid &deviceId); DeviceError removeConfiguredDevice(const DeviceId &deviceId);
Device* findConfiguredDevice(const QUuid &id) const; Device* findConfiguredDevice(const DeviceId &id) const;
QList<Device*> findConfiguredDevices(const QUuid &deviceClassId) const; QList<Device*> findConfiguredDevices(const DeviceClassId &deviceClassId) const;
DeviceClass findDeviceClassforEvent(const QUuid &eventTypeId) const;
DeviceClass findDeviceClass(const QUuid &deviceClassId) const; DeviceClass findDeviceClass(const QUuid &deviceClassId) const;
signals: signals:
@ -84,6 +88,7 @@ private slots:
void loadPlugins(); void loadPlugins();
void loadConfiguredDevices(); void loadConfiguredDevices();
void storeConfiguredDevices(); void storeConfiguredDevices();
void createNewAutoDevices();
// Only connect this to Devices. It will query the sender() // Only connect this to Devices. It will query the sender()
void slotDeviceStateValueChanged(const QUuid &stateTypeId, const QVariant &value); void slotDeviceStateValueChanged(const QUuid &stateTypeId, const QVariant &value);
@ -92,6 +97,7 @@ private slots:
void timerEvent(); void timerEvent();
private: private:
DeviceError addConfiguredDeviceInternal(const DeviceClassId &deviceClassId, const QVariantMap &params, const DeviceId id = DeviceId::createDeviceId());
bool setupDevice(Device *device); bool setupDevice(Device *device);
QHash<VendorId, Vendor> m_supportedVendors; QHash<VendorId, Vendor> m_supportedVendors;

View File

@ -42,7 +42,9 @@
DeviceClass::DeviceClass(const QUuid &pluginId, const VendorId &vendorId, const DeviceClassId &id): DeviceClass::DeviceClass(const QUuid &pluginId, const VendorId &vendorId, const DeviceClassId &id):
m_id(id), m_id(id),
m_vendorId(vendorId), m_vendorId(vendorId),
m_pluginId(pluginId) m_pluginId(pluginId),
m_createMethod(CreateMethodUser),
m_setupMethod(SetupMethodJustAdd)
{ {
} }
@ -139,6 +141,26 @@ void DeviceClass::setParams(const QVariantList &params)
m_params = params; m_params = params;
} }
DeviceClass::CreateMethod DeviceClass::createMethod() const
{
return m_createMethod;
}
void DeviceClass::setCreateMethod(DeviceClass::CreateMethod createMethod)
{
m_createMethod = createMethod;
}
DeviceClass::SetupMethod DeviceClass::setupMethod() const
{
return m_setupMethod;
}
void DeviceClass::setSetupMethod(DeviceClass::SetupMethod setupMethod)
{
m_setupMethod = setupMethod;
}
/*! Compare this \a deviceClass to another. This is effectively the same as calling a.id() == b.id(). Returns true if the ids match.*/ /*! Compare this \a deviceClass to another. This is effectively the same as calling a.id() == b.id(). Returns true if the ids match.*/
bool DeviceClass::operator==(const DeviceClass &deviceClass) const bool DeviceClass::operator==(const DeviceClass &deviceClass) const
{ {

View File

@ -31,6 +31,18 @@
class DeviceClass class DeviceClass
{ {
public: public:
enum CreateMethod {
CreateMethodUser,
CreateMethodAuto,
CreateMethodDiscovery
};
enum SetupMethod {
SetupMethodJustAdd,
SetupMethodDisplayPin,
SetupMethodEnterPin,
SetupMethodPushButton
};
DeviceClass(const QUuid &pluginId = QUuid(), const VendorId &vendorId = VendorId(), const DeviceClassId &id = DeviceClassId()); DeviceClass(const QUuid &pluginId = QUuid(), const VendorId &vendorId = VendorId(), const DeviceClassId &id = DeviceClassId());
DeviceClassId id() const; DeviceClassId id() const;
@ -53,6 +65,11 @@ public:
QVariantList params() const; QVariantList params() const;
void setParams(const QVariantList &params); void setParams(const QVariantList &params);
CreateMethod createMethod() const;
void setCreateMethod(CreateMethod createMethod);
SetupMethod setupMethod() const;
void setSetupMethod(SetupMethod setupMethod);
bool operator==(const DeviceClass &device) const; bool operator==(const DeviceClass &device) const;
private: private:
@ -64,6 +81,8 @@ private:
QList<EventType> m_events; QList<EventType> m_events;
QList<ActionType> m_actions; QList<ActionType> m_actions;
QVariantList m_params; QVariantList m_params;
CreateMethod m_createMethod;
SetupMethod m_setupMethod;
}; };
#endif #endif

View File

@ -104,6 +104,28 @@ DevicePlugin::~DevicePlugin()
} }
/*! Override this if your plugin supports Device with DeviceClass::CreationMethodAuto.
This will be called at startup, after the configured devices have been loaded.
You should walk through loadedDevices and check whether all the detected devices
are contained in there. If all the detected devices are already contained, return
false. If instead you've found a new device which isn't known to the system yet,
fill in the parameters of the passed device with some details that makes it possible
for you to match this Device object with the detected hardware. After that, return true.
The DeviceManager will then insert the device into its database and call deviceCreated()
for this device. Therefore you should not do any hardware initialisation in this state yet
but rather wait for the subsequent deviceCreated() call to set it up like in any other
case where Device can be created.
Returning false will cause the passed device object to be destroyed.
If you have detected multiple new devices, just load them one by one. The DeviceManager
will continue to call this method until you return false.
*/
bool DevicePlugin::configureAutoDevice(QList<Device*> loadedDevices, Device *device) const
{
Q_UNUSED(loadedDevices)
Q_UNUSED(device)
return false;
}
/*! This will be called when a new device is created. The plugin has the chance to do some setup. /*! This will be called when a new device is created. The plugin has the chance to do some setup.
Return false if something bad happened during the setup. The device will be disabled. Return false if something bad happened during the setup. The device will be disabled.
*/ */

View File

@ -22,6 +22,7 @@
#include "devicemanager.h" #include "devicemanager.h"
#include "deviceclass.h" #include "deviceclass.h"
#include "typeutils.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"
@ -47,6 +48,8 @@ public:
virtual QList<DeviceClass> supportedDevices() const = 0; virtual QList<DeviceClass> supportedDevices() const = 0;
virtual DeviceManager::HardwareResources requiredHardware() const = 0; virtual DeviceManager::HardwareResources requiredHardware() const = 0;
virtual bool configureAutoDevice(QList<Device *> loadedDevices, Device *device) const;
virtual bool deviceCreated(Device *device); virtual bool deviceCreated(Device *device);
virtual void deviceRemoved(Device *device); virtual void deviceRemoved(Device *device);
@ -58,7 +61,7 @@ public:
virtual void setConfiguration(const QVariantMap &configuration); virtual void setConfiguration(const QVariantMap &configuration);
public slots: public slots:
virtual void executeAction(Device *device, const Action &action) {Q_UNUSED(device) Q_UNUSED(action)} virtual DeviceManager::DeviceError executeAction(Device *device, const Action &action) {Q_UNUSED(device) Q_UNUSED(action)}
signals: signals:

View File

@ -22,6 +22,7 @@ DECLARE_TYPE_ID(Device)
DECLARE_TYPE_ID(EventType) DECLARE_TYPE_ID(EventType)
DECLARE_TYPE_ID(StateType) DECLARE_TYPE_ID(StateType)
DECLARE_TYPE_ID(ActionType) DECLARE_TYPE_ID(ActionType)
DECLARE_TYPE_ID(Plugin)
#endif // TYPEUTILS_H #endif // TYPEUTILS_H

View File

@ -0,0 +1,107 @@
#include "bobclient.h"
#include "libboblight/boblight.h"
#include <QDebug>
BobClient::BobClient(QObject *parent) :
QObject(parent),
m_connected(false),
m_port(-1)
{
m_lastSyncTime = QTime::currentTime();
m_resyncTimer.setInterval(200);
m_resyncTimer.setSingleShot(true);
QObject::connect(&m_resyncTimer, SIGNAL(timeout()), SLOT(sync()));
}
bool BobClient::connect(const QString &hostname, int port)
{
qDebug() << "Connecting to boblightd\n";
m_boblight = boblight_init();
//try to connect, if we can't then bitch to stderr and destroy boblight
if (!boblight_connect(m_boblight, hostname.toLatin1().data(), port, 5000000) ||
!boblight_setpriority(m_boblight, 1))
{
qDebug() << "Failed to connect:" << boblight_geterror(m_boblight);
boblight_destroy(m_boblight);
m_connected = false;
return false;
}
qDebug() << "Connection to boblightd opened\n";
m_hostname = hostname;
m_port = port;
m_connected = true;
return true;
}
bool BobClient::connected() const
{
return m_connected;
}
void BobClient::setPriority(int priority)
{
qDebug() << "setting new priority:" << priority;
qDebug() << "setting priority to" << priority << boblight_setpriority(m_boblight, priority);
}
void BobClient::setColor(int channel, QColor color)
{
if(channel == -1) {
for(int i = 0; i < lightsCount(); ++i) {
setColor(i, color);
}
} else {
m_colors[channel] = color;
// qDebug() << "set channel" << channel << "to color" << color;
}
}
void BobClient::sync()
{
if(!m_connected) {
qDebug() << "Not connected to boblight. Cannot sync";
return;
}
if(m_lastSyncTime.addMSecs(50) > QTime::currentTime()) {
if(!m_resyncTimer.isActive()) {
m_resyncTimer.start();
}
return;
}
//qDebug() << "syncing";
m_lastSyncTime = QTime::currentTime();
for(int i = 0; i < lightsCount(); ++i) {
//load the color into int array
int rgb[3] = {m_colors[i].red() * m_colors[i].alphaF(), m_colors[i].green() * m_colors[i].alphaF(), m_colors[i].blue() * m_colors[i].alphaF()};
// qDebug() << "set color" << rgb[0] << rgb[1] << rgb[2];
//set all lights to the color we want and send it
boblight_addpixel(m_boblight, i, rgb);
}
if (!boblight_sendrgb(m_boblight, 1, NULL)) //some error happened, probably connection broken, so bitch and try again
{
qDebug() << "Boblight connection error!";
qDebug() << boblight_geterror(m_boblight);
boblight_destroy(m_boblight);
m_connected = false;
connect(m_hostname, m_port);
}
}
int BobClient::lightsCount()
{
return boblight_getnrlights(m_boblight);
}
QColor BobClient::currentColor(int channel)
{
return m_colors[channel];
}

View File

@ -0,0 +1,40 @@
#ifndef BOBCLIENT_H
#define BOBCLIENT_H
#include <QObject>
#include <QTimer>
#include <QMap>
#include <QColor>
#include <QTime>
class BobClient : public QObject
{
Q_OBJECT
public:
explicit BobClient(QObject *parent = 0);
bool connect(const QString &hostname, int port);
bool connected() const;
int lightsCount();
QColor currentColor(int channel);
void setPriority(int priority);
signals:
public slots:
void setColor(int channel, QColor color);
void sync();
private:
QMap<int, QColor> m_colors; //channel, color
void *m_boblight;
bool m_connected;
QString m_hostname;
int m_port;
QTime m_lastSyncTime;
QTimer m_resyncTimer;
};
#endif // BOBCLIENT_H

View File

@ -0,0 +1,17 @@
include(../../plugins.pri)
TARGET = $$qtLibraryTarget(guh_devicepluginboblight)
INCLUDEPATH += /usr/local/include/
LIBS += -L/usr/local/lib/libboblight.a
SOURCES += \
devicepluginboblight.cpp \
bobclient.cpp \
HEADERS += \
devicepluginboblight.h \
bobclient.h \

View File

@ -0,0 +1,138 @@
#include "devicepluginboblight.h"
#include "plugin/device.h"
#include "devicemanager.h"
#include "bobclient.h"
#include <QDebug>
#include <QStringList>
VendorId boblightVendorId = VendorId("8c5e8d4c-b5ed-4bfe-b30d-35c2790ec100");
QUuid boblightPluginUuid = QUuid("e1647872-c0f5-4680-b49b-3924e5b54dcd");
DeviceClassId boblightDeviceClassId = DeviceClassId("1647c61c-db14-461e-8060-8a3533d5d92f");
StateTypeId colorStateTypeId = StateTypeId("97ec80cd-43a9-40fa-93b7-d1580043d981");
ActionTypeId setColorActionTypeId = ActionTypeId("668e1aa3-fa13-49ce-8630-17a5c0a7c34b");
DevicePluginBoblight::DevicePluginBoblight()
{
m_bobClient = new BobClient(this);
m_config.insert("boblighthost", "localhost");
m_config.insert("boblightport", "19333");
connectToBoblight();
}
QList<Vendor> DevicePluginBoblight::supportedVendors() const
{
QList<Vendor> ret;
Vendor guh(boblightVendorId, "http://code.google.com/p/boblight/");
ret.append(guh);
return ret;
}
QList<DeviceClass> DevicePluginBoblight::supportedDevices() const
{
QList<DeviceClass> ret;
DeviceClass deviceClassBoblight(pluginId(), boblightVendorId, boblightDeviceClassId);
deviceClassBoblight.setName("Boblight");
deviceClassBoblight.setCreateMethod(DeviceClass::CreateMethodAuto);
QList<StateType> boblightStates;
StateType colorState(colorStateTypeId);
colorState.setName("color");
colorState.setType(QVariant::Color);
colorState.setDefaultValue(QColor(Qt::black));
boblightStates.append(colorState);
deviceClassBoblight.setStates(boblightStates);
QList<ActionType> boblightActons;
ActionType setColorAction(setColorActionTypeId);
setColorAction.setName("Set color");
QVariantList actionParamsSetColor;
QVariantMap actionParamSetColor;
actionParamSetColor.insert("name", "color");
actionParamSetColor.insert("type", "color");
actionParamsSetColor.append(actionParamSetColor);
setColorAction.setParameters(actionParamsSetColor);
boblightActons.append(setColorAction);
deviceClassBoblight.setActions(boblightActons);
ret.append(deviceClassBoblight);
return ret;
}
DeviceManager::HardwareResources DevicePluginBoblight::requiredHardware() const
{
return DeviceManager::HardwareResourceNone;
}
bool DevicePluginBoblight::configureAutoDevice(QList<Device *> loadedDevices, Device *device) const
{
if (!m_bobClient->connected()) {
return false;
}
if (loadedDevices.count() < m_bobClient->lightsCount()) {
int index = loadedDevices.count();
device->setName("Boblight Channel " + QString::number(index));
QVariantMap params;
params.insert("channel", index);
device->setParams(params);
device->setStateValue(colorStateTypeId, m_bobClient->currentColor(index));
return true;
}
return false;
}
QString DevicePluginBoblight::pluginName() const
{
return "Boblight client";
}
QUuid DevicePluginBoblight::pluginId() const
{
return boblightPluginUuid;
}
QVariantMap DevicePluginBoblight::configuration() const
{
return m_config;
}
void DevicePluginBoblight::setConfiguration(const QVariantMap &configuration)
{
m_config = configuration;
connectToBoblight();
}
DeviceManager::DeviceError DevicePluginBoblight::executeAction(Device *device, const Action &action)
{
if (!m_bobClient->connected()) {
return DeviceManager::DeviceErrorSetupFailed;
}
QColor newColor = action.params().first().value<QColor>();
if (!newColor.isValid()) {
return DeviceManager::DeviceErrorActionParameterError;
}
qDebug() << "executing boblight action" << newColor;
m_bobClient->setColor(device->params().value("channel").toInt(), newColor);
m_bobClient->sync();
device->setStateValue(colorStateTypeId, newColor);
return DeviceManager::DeviceErrorNoError;
}
void DevicePluginBoblight::connectToBoblight()
{
m_bobClient->connect(m_config.value("boblighthost").toString(), m_config.value("boblightport").toInt());
}

View File

@ -0,0 +1,43 @@
#ifndef DEVICEPLUGINBOBLIGHT_H
#define DEVICEPLUGINBOBLIGHT_H
#include "plugin/deviceplugin.h"
#include <QProcess>
class BobClient;
class DevicePluginBoblight : public DevicePlugin
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "org.hiveyourhome.DevicePlugin" FILE "devicepluginboblight.json")
Q_INTERFACES(DevicePlugin)
public:
explicit DevicePluginBoblight();
QList<Vendor> supportedVendors() const override;
QList<DeviceClass> supportedDevices() const override;
DeviceManager::HardwareResources requiredHardware() const override;
bool configureAutoDevice(QList<Device *> loadedDevices, Device *device) const override;
QString pluginName() const override;
QUuid pluginId() const override;
QVariantMap configuration() const override;
void setConfiguration(const QVariantMap &configuration) override;
public slots:
DeviceManager::DeviceError executeAction(Device *device, const Action &action);
private slots:
void connectToBoblight();
private:
BobClient *m_bobClient;
QVariantMap m_config;
};
#endif // DEVICEPLUGINBOBLIGHT_H

View File

@ -0,0 +1 @@
{}

View File

@ -124,13 +124,13 @@ QUuid DevicePluginConrad::pluginId() const
return QUuid("1fd1a076-f229-4ec6-b501-48ddd15935e4"); return QUuid("1fd1a076-f229-4ec6-b501-48ddd15935e4");
} }
void DevicePluginConrad::executeAction(Device *device, const Action &action) DeviceManager::DeviceError DevicePluginConrad::executeAction(Device *device, const Action &action)
{ {
QList<int> rawData; QList<int> rawData;
QByteArray binCode; QByteArray binCode;
return DeviceManager::DeviceErrorNoError;
} }
void DevicePluginConrad::radioData(QList<int> rawData) void DevicePluginConrad::radioData(QList<int> rawData)

View File

@ -41,7 +41,7 @@ public:
void radioData(QList<int> rawData) override; void radioData(QList<int> rawData) override;
public slots: public slots:
void executeAction(Device *device, const Action &action) override; DeviceManager::DeviceError executeAction(Device *device, const Action &action) override;
}; };

View File

@ -8,4 +8,6 @@ SUBDIRS += elro \
# weatherground \ # weatherground \
openweathermap \ openweathermap \
# boblight \ boblight {
SUBDIRS += boblight
}

View File

@ -221,7 +221,7 @@ QUuid DevicePluginElro::pluginId() const
return QUuid("2b267f81-d9ae-4f4f-89a0-7386b547cfd3"); return QUuid("2b267f81-d9ae-4f4f-89a0-7386b547cfd3");
} }
void DevicePluginElro::executeAction(Device *device, const Action &action) DeviceManager::DeviceError DevicePluginElro::executeAction(Device *device, const Action &action)
{ {
QList<int> rawData; QList<int> rawData;
@ -314,6 +314,7 @@ void DevicePluginElro::executeAction(Device *device, const Action &action)
//qDebug() << "rawData" << rawData; //qDebug() << "rawData" << rawData;
qDebug() << "transmit" << pluginName() << action.params().value("power").toBool(); qDebug() << "transmit" << pluginName() << action.params().value("power").toBool();
transmitData(rawData); transmitData(rawData);
return DeviceManager::DeviceErrorNoError;
} }
void DevicePluginElro::radioData(QList<int> rawData) void DevicePluginElro::radioData(QList<int> rawData)

View File

@ -41,7 +41,7 @@ public:
void radioData(QList<int> rawData) override; void radioData(QList<int> rawData) override;
public slots: public slots:
void executeAction(Device *device, const Action &action) override; DeviceManager::DeviceError executeAction(Device *device, const Action &action) override;
}; };

View File

@ -357,7 +357,7 @@ QUuid DevicePluginIntertechno::pluginId() const
return QUuid("e998d934-0397-42c1-ad63-9141bcac8563"); return QUuid("e998d934-0397-42c1-ad63-9141bcac8563");
} }
void DevicePluginIntertechno::executeAction(Device *device, const Action &action) DeviceManager::DeviceError DevicePluginIntertechno::executeAction(Device *device, const Action &action)
{ {
QList<int> rawData; QList<int> rawData;
@ -400,7 +400,7 @@ void DevicePluginIntertechno::executeAction(Device *device, const Action &action
}else if(familyCode == "P"){ }else if(familyCode == "P"){
binCode.append("01010101"); binCode.append("01010101");
}else{ }else{
return; return DeviceManager::DeviceErrorDeviceParameterError;
} }
QString buttonCode = device->params().value("buttonCode").toString(); QString buttonCode = device->params().value("buttonCode").toString();
@ -440,7 +440,7 @@ void DevicePluginIntertechno::executeAction(Device *device, const Action &action
}else if(familyCode == "16"){ }else if(familyCode == "16"){
binCode.append("01010101"); binCode.append("01010101");
}else{ }else{
return; return DeviceManager::DeviceErrorDeviceParameterError;
} }
// ======================================= // =======================================
@ -479,6 +479,8 @@ void DevicePluginIntertechno::executeAction(Device *device, const Action &action
qDebug() << "transmit" << pluginName() << familyCode << buttonCode << action.params().value("power").toBool(); qDebug() << "transmit" << pluginName() << familyCode << buttonCode << action.params().value("power").toBool();
transmitData(rawData); transmitData(rawData);
return DeviceManager::DeviceErrorNoError;
} }
void DevicePluginIntertechno::radioData(QList<int> rawData) void DevicePluginIntertechno::radioData(QList<int> rawData)

View File

@ -41,7 +41,7 @@ public:
void radioData(QList<int> rawData) override; void radioData(QList<int> rawData) override;
public slots: public slots:
void executeAction(Device *device, const Action &action) override; DeviceManager::DeviceError executeAction(Device *device, const Action &action) override;
}; };

View File

@ -27,6 +27,7 @@
VendorId guhVendorId = VendorId("2062d64d-3232-433c-88bc-0d33c0ba2ba6"); VendorId guhVendorId = VendorId("2062d64d-3232-433c-88bc-0d33c0ba2ba6");
DeviceClassId mockDeviceClassId = DeviceClassId("753f0d32-0468-4d08-82ed-1964aab03298"); DeviceClassId mockDeviceClassId = DeviceClassId("753f0d32-0468-4d08-82ed-1964aab03298");
DeviceClassId mockDeviceAutoClassId = DeviceClassId("ab4257b3-7548-47ee-9bd4-7dc3004fd197");
EventTypeId mockEvent1Id = EventTypeId("45bf3752-0fc6-46b9-89fd-ffd878b5b22b"); 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");
@ -103,6 +104,19 @@ QList<DeviceClass> DevicePluginMock::supportedDevices() const
ret.append(deviceClassMock); ret.append(deviceClassMock);
// Auto created mock device
DeviceClass deviceClassMockAuto(pluginId(), guhVendorId, mockDeviceAutoClassId);
deviceClassMockAuto.setName("Mock Device (Auto created)");
deviceClassMockAuto.setCreateMethod(DeviceClass::CreateMethodAuto);
mockParams.clear();
deviceClassMockAuto.setParams(mockParams);
deviceClassMockAuto.setStates(mockStates);
deviceClassMockAuto.setEvents(mockEvents);
deviceClassMockAuto.setActions(mockActions);
ret.append(deviceClassMockAuto);
return ret; return ret;
} }
@ -144,7 +158,24 @@ void DevicePluginMock::deviceRemoved(Device *device)
m_daemons.take(device)->deleteLater(); m_daemons.take(device)->deleteLater();
} }
void DevicePluginMock::executeAction(Device *device, const Action &action) bool DevicePluginMock::configureAutoDevice(QList<Device *> loadedDevices, Device *device) const
{
Q_ASSERT(device->deviceClassId() == mockDeviceAutoClassId);
qDebug() << "checking loadedDevices" << loadedDevices.count();
// We only want to have one auto mock device. So if there's already anything in loadedDevices, don't crearte a new one.
if (loadedDevices.count() > 0) {
return false;
}
device->setName("Mock Device (Auto created)");
QVariantMap params;
params.insert("httpport", 4242);
device->setParams(params);
return true;
}
DeviceManager::DeviceError DevicePluginMock::executeAction(Device *device, const Action &action)
{ {
qDebug() << "Should execute action" << action.actionTypeId(); qDebug() << "Should execute action" << action.actionTypeId();
m_daemons.value(device)->actionExecuted(action.actionTypeId()); m_daemons.value(device)->actionExecuted(action.actionTypeId());

View File

@ -45,8 +45,10 @@ public:
bool deviceCreated(Device *device) override; bool deviceCreated(Device *device) override;
void deviceRemoved(Device *device) override; void deviceRemoved(Device *device) override;
bool configureAutoDevice(QList<Device *> loadedDevices, Device *device) const override;
public slots: public slots:
void executeAction(Device *device, const Action &action) override; DeviceManager::DeviceError executeAction(Device *device, const Action &action) override;
private slots: private slots:
void setState(const StateTypeId &stateTypeId, const QVariant &value); void setState(const StateTypeId &stateTypeId, const QVariant &value);

View File

@ -68,8 +68,16 @@ QVariantMap ActionHandler::ExecuteAction(const QVariantMap &params)
returns.insert("errorMessage", "No such device"); returns.insert("errorMessage", "No such device");
returns.insert("success", false); returns.insert("success", false);
break; break;
case DeviceManager::DeviceErrorActionTypeNotFound:
returns.insert("errorMessage", "ActionType not found");
returns.insert("success", false);
break;
case DeviceManager::DeviceErrorMissingParameter:
returns.insert("errorMessage", "Missing parameter");
returns.insert("success", false);
break;
default: default:
returns.insert("errorMessage", "Unknown error."); returns.insert("errorMessage", QString("Unknown error %1").arg(error));
returns.insert("success", false); returns.insert("success", false);
} }

View File

@ -57,13 +57,13 @@ DeviceHandler::DeviceHandler(QObject *parent) :
setReturns("GetPlugins", returns); setReturns("GetPlugins", returns);
params.clear(); returns.clear(); params.clear(); returns.clear();
setDescription("SetPluginParams", "Set a plugin's params."); setDescription("SetPluginConfiguration", "Set a plugin's params.");
params.insert("pluginId", "uuid"); params.insert("pluginId", "uuid");
QVariantList pluginParams; QVariantList pluginParams;
pluginParams.append(JsonTypes::paramTypeRef()); pluginParams.append(JsonTypes::paramTypeRef());
params.insert("pluginParams", pluginParams); params.insert("pluginParams", pluginParams);
setParams("SetPluginParams", params); setParams("SetPluginConfiguration", params);
setReturns("SetPluginParams", returns); setReturns("SetPluginConfiguration", returns);
params.clear(); returns.clear(); params.clear(); returns.clear();
setDescription("AddConfiguredDevice", "Add a configured device."); setDescription("AddConfiguredDevice", "Add a configured device.");
@ -190,11 +190,11 @@ QVariantMap DeviceHandler::GetPlugins(const QVariantMap &params) const
return returns; return returns;
} }
QVariantMap DeviceHandler::SetPluginParams(const QVariantMap &params) QVariantMap DeviceHandler::SetPluginConfiguration(const QVariantMap &params)
{ {
QUuid pluginId = params.value("pluginId").toUuid(); PluginId pluginId = PluginId(params.value("pluginId").toString());
QVariantMap pluginParams = params.value("pluginParams").toMap(); QVariantMap pluginParams = params.value("pluginParams").toMap();
GuhCore::instance()->deviceManager()->plugin(pluginId)->setConfiguration(pluginParams); GuhCore::instance()->deviceManager()->setPluginConfig(pluginId, pluginParams);
return QVariantMap(); return QVariantMap();
} }
@ -223,6 +223,10 @@ QVariantMap DeviceHandler::AddConfiguredDevice(const QVariantMap &params)
returns.insert("errorMessage", "Error creating device. Device setup failed."); returns.insert("errorMessage", "Error creating device. Device setup failed.");
returns.insert("success", false); returns.insert("success", false);
break; break;
case DeviceManager::DeviceErrorCreationNotSupported:
returns.insert("errorMessage", "Error creating device. This device can't be created this way.");
returns.insert("success", false);
break;
default: default:
returns.insert("errorMessage", "Unknown error."); returns.insert("errorMessage", "Unknown error.");
returns.insert("success", false); returns.insert("success", false);
@ -245,7 +249,7 @@ QVariantMap DeviceHandler::GetConfiguredDevices(const QVariantMap &params) const
QVariantMap DeviceHandler::RemoveConfiguredDevice(const QVariantMap &params) QVariantMap DeviceHandler::RemoveConfiguredDevice(const QVariantMap &params)
{ {
QVariantMap returns; QVariantMap returns;
switch(GuhCore::instance()->deviceManager()->removeConfiguredDevice(params.value("deviceId").toUuid())) { switch(GuhCore::instance()->deviceManager()->removeConfiguredDevice(DeviceId(params.value("deviceId").toString()))) {
case DeviceManager::DeviceErrorNoError: case DeviceManager::DeviceErrorNoError:
returns.insert("success", true); returns.insert("success", true);
returns.insert("errorMessage", ""); returns.insert("errorMessage", "");
@ -303,7 +307,7 @@ QVariantMap DeviceHandler::GetStateValue(const QVariantMap &params) const
{ {
QVariantMap returns; QVariantMap returns;
Device *device = GuhCore::instance()->deviceManager()->findConfiguredDevice(params.value("deviceId").toUuid()); Device *device = GuhCore::instance()->deviceManager()->findConfiguredDevice(DeviceId(params.value("deviceId").toString()));
if (!device) { if (!device) {
returns.insert("success", false); returns.insert("success", false);
returns.insert("errorMessage", "No such device"); returns.insert("errorMessage", "No such device");

View File

@ -35,7 +35,7 @@ public:
Q_INVOKABLE QVariantMap GetPlugins(const QVariantMap &params) const; Q_INVOKABLE QVariantMap GetPlugins(const QVariantMap &params) const;
Q_INVOKABLE QVariantMap SetPluginParams(const QVariantMap &params); Q_INVOKABLE QVariantMap SetPluginConfiguration(const QVariantMap &params);
Q_INVOKABLE QVariantMap AddConfiguredDevice(const QVariantMap &params); Q_INVOKABLE QVariantMap AddConfiguredDevice(const QVariantMap &params);

View File

@ -29,6 +29,8 @@ QString JsonTypes::s_lastError;
QVariantList JsonTypes::s_basicTypes; QVariantList JsonTypes::s_basicTypes;
QVariantList JsonTypes::s_ruleTypes; QVariantList JsonTypes::s_ruleTypes;
QVariantList JsonTypes::s_createMethodTypes;
QVariantList JsonTypes::s_setupMethodTypes;
QVariantMap JsonTypes::s_paramType; QVariantMap JsonTypes::s_paramType;
QVariantMap JsonTypes::s_param; QVariantMap JsonTypes::s_param;
@ -49,6 +51,8 @@ void JsonTypes::init()
// BasicTypes // BasicTypes
s_basicTypes << "uuid" << "string" << "integer" << "double" << "bool"; s_basicTypes << "uuid" << "string" << "integer" << "double" << "bool";
s_ruleTypes << "RuleTypeMatchAll" << "RuleTypeMatchAny"; s_ruleTypes << "RuleTypeMatchAll" << "RuleTypeMatchAny";
s_createMethodTypes << "CreateMethodUser" << "CreateMethodAuto" << "CreateMethodDiscovery";
s_setupMethodTypes << "SetupMethodJustAdd" << "SetupMethodDisplayPin" << "SetupMethodEnterPin" << "SetupMethodPushButton";
// ParamType // ParamType
s_paramType.insert("name", "string"); s_paramType.insert("name", "string");
@ -107,6 +111,8 @@ void JsonTypes::init()
s_deviceClass.insert("events", QVariantList() << eventTypeRef()); s_deviceClass.insert("events", QVariantList() << eventTypeRef());
s_deviceClass.insert("actions", QVariantList() << actionTypeRef()); s_deviceClass.insert("actions", QVariantList() << actionTypeRef());
s_deviceClass.insert("params", QVariantList() << paramTypeRef()); s_deviceClass.insert("params", QVariantList() << paramTypeRef());
s_deviceClass.insert("setupMethod", setupMethodTypesRef());
s_deviceClass.insert("createMethod", createMethodTypesRef());
// Device // Device
s_device.insert("id", "uuid"); s_device.insert("id", "uuid");
@ -133,6 +139,8 @@ QVariantMap JsonTypes::allTypes()
QVariantMap allTypes; QVariantMap allTypes;
allTypes.insert("BasicType", basicTypes()); allTypes.insert("BasicType", basicTypes());
allTypes.insert("ParamType", paramTypeDescription()); allTypes.insert("ParamType", paramTypeDescription());
allTypes.insert("CreateMethodType", createMethodTypes());
allTypes.insert("SetupMethodType", setupMethodTypes());
allTypes.insert("StateType", stateTypeDescription()); allTypes.insert("StateType", stateTypeDescription());
allTypes.insert("EventType", eventTypeDescription()); allTypes.insert("EventType", eventTypeDescription());
allTypes.insert("ActionType", actionTypeDescription()); allTypes.insert("ActionType", actionTypeDescription());
@ -224,6 +232,8 @@ QVariantMap JsonTypes::packDeviceClass(const DeviceClass &deviceClass)
variant.insert("states", stateTypes); variant.insert("states", stateTypes);
variant.insert("events", eventTypes); variant.insert("events", eventTypes);
variant.insert("actions", actionTypes); variant.insert("actions", actionTypes);
variant.insert("createMethod", s_createMethodTypes.at(deviceClass.createMethod()));
variant.insert("setupMethod", s_setupMethodTypes.at(deviceClass.setupMethod()));
return variant; return variant;
} }
@ -406,6 +416,18 @@ QPair<bool, QString> JsonTypes::validateVariant(const QVariant &templateVariant,
qDebug() << "value not allowed in" << ruleTypesRef(); qDebug() << "value not allowed in" << ruleTypesRef();
return result; return result;
} }
} else if (refName == createMethodTypesRef()) {
QPair<bool, QString> result = validateCreateMethodType(variant);
if (!result.first) {
qDebug() << "value not allowed in" << createMethodTypesRef();
return result;
}
} else if (refName == setupMethodTypesRef()) {
QPair<bool, QString> result = validateSetupMethodType(variant);
if (!result.first) {
qDebug() << "value not allowed in" << createMethodTypesRef();
return result;
}
} else { } else {
qDebug() << "unhandled ref:" << refName; qDebug() << "unhandled ref:" << refName;
return report(false, QString("Unhandled ref %1. Server implementation incomplete.").arg(refName)); return report(false, QString("Unhandled ref %1. Server implementation incomplete.").arg(refName));
@ -464,3 +486,13 @@ QPair<bool, QString> JsonTypes::validateRuleType(const QVariant &variant)
{ {
return report(s_ruleTypes.contains(variant.toString()), QString("Unknown rules type %1").arg(variant.toString())); return report(s_ruleTypes.contains(variant.toString()), QString("Unknown rules type %1").arg(variant.toString()));
} }
QPair<bool, QString> JsonTypes::validateCreateMethodType(const QVariant &variant)
{
return report(s_createMethodTypes.contains(variant.toString()), QString("Unknwon createMethod type %1").arg(variant.toString()));
}
QPair<bool, QString> JsonTypes::validateSetupMethodType(const QVariant &variant)
{
return report(s_setupMethodTypes.contains(variant.toString()), QString("Unknwon setupMethod type %1").arg(variant.toString()));
}

View File

@ -63,6 +63,8 @@ public:
DECLARE_TYPE(basicTypes, "BasicType") DECLARE_TYPE(basicTypes, "BasicType")
DECLARE_TYPE(ruleTypes, "RuleType") DECLARE_TYPE(ruleTypes, "RuleType")
DECLARE_TYPE(createMethodTypes, "CreateMethodType")
DECLARE_TYPE(setupMethodTypes, "SetupMethodType")
DECLARE_OBJECT(paramType, "ParamType") DECLARE_OBJECT(paramType, "ParamType")
DECLARE_OBJECT(param, "Param") DECLARE_OBJECT(param, "Param")
DECLARE_OBJECT(stateType, "StateType") DECLARE_OBJECT(stateType, "StateType")
@ -94,6 +96,8 @@ public:
static QPair<bool, QString> validateVariant(const QVariant &templateVariant, const QVariant &variant); static QPair<bool, QString> validateVariant(const QVariant &templateVariant, const QVariant &variant);
static QPair<bool, QString> validateBasicType(const QVariant &variant); static QPair<bool, QString> validateBasicType(const QVariant &variant);
static QPair<bool, QString> validateRuleType(const QVariant &variant); static QPair<bool, QString> validateRuleType(const QVariant &variant);
static QPair<bool, QString> validateCreateMethodType(const QVariant &variant);
static QPair<bool, QString> validateSetupMethodType(const QVariant &variant);
private: private:
static bool s_initialized; static bool s_initialized;

View File

@ -29,6 +29,7 @@ Q_IMPORT_PLUGIN(DevicePluginConrad)
Q_IMPORT_PLUGIN(DevicePluginMock) Q_IMPORT_PLUGIN(DevicePluginMock)
//Q_IMPORT_PLUGIN(DevicePluginWeatherground) //Q_IMPORT_PLUGIN(DevicePluginWeatherground)
Q_IMPORT_PLUGIN(DevicePluginOpenweathermap) Q_IMPORT_PLUGIN(DevicePluginOpenweathermap)
Q_IMPORT_PLUGIN(DevicePluginBoblight)
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {

View File

@ -156,9 +156,6 @@ RuleEngine::RuleError RuleEngine::addRule(const Event &event, const QList<Action
/*! Add a new \l{Rule} with the given \a event, \a states and \a actions to the engine. */ /*! Add a new \l{Rule} with the given \a event, \a states and \a actions to the engine. */
RuleEngine::RuleError RuleEngine::addRule(const Event &event, const QList<State> &states, const QList<Action> &actions) RuleEngine::RuleError RuleEngine::addRule(const Event &event, const QList<State> &states, const QList<Action> &actions)
{ {
qDebug() << "adding rule: Event:" << event.eventTypeId() << "with" << actions.count() << "actions";
DeviceClass eventDeviceClass = GuhCore::instance()->deviceManager()->findDeviceClassforEvent(event.eventTypeId());
Device *device = GuhCore::instance()->deviceManager()->findConfiguredDevice(event.deviceId()); Device *device = GuhCore::instance()->deviceManager()->findConfiguredDevice(event.deviceId());
if (!device) { if (!device) {
qWarning() << "Cannot create rule. No configured device for eventTypeId" << event.eventTypeId(); qWarning() << "Cannot create rule. No configured device for eventTypeId" << event.eventTypeId();

View File

@ -23,3 +23,7 @@ LIBS += -L../plugins/deviceplugins/conrad -lguh_devicepluginconrad
LIBS += -L../plugins/deviceplugins/mock -lguh_devicepluginmock LIBS += -L../plugins/deviceplugins/mock -lguh_devicepluginmock
#LIBS += -L../plugins/deviceplugins/weatherground -lguh_devicepluginweatherground #LIBS += -L../plugins/deviceplugins/weatherground -lguh_devicepluginweatherground
LIBS += -L../plugins/deviceplugins/openweathermap -lguh_devicepluginopenweathermap LIBS += -L../plugins/deviceplugins/openweathermap -lguh_devicepluginopenweathermap
boblight {
LIBS += -L../plugins/deviceplugins/boblight -lguh_devicepluginboblight -L/usr/local/lib/ -lboblight
}

View File

@ -34,6 +34,7 @@ int mockDevice2Port = 7331;
extern VendorId guhVendorId; extern VendorId guhVendorId;
extern DeviceClassId mockDeviceClassId; extern DeviceClassId mockDeviceClassId;
extern DeviceClassId mockDeviceAutoClassId;
extern ActionTypeId mockAction1Id; extern ActionTypeId mockAction1Id;
extern EventTypeId mockEvent1Id; extern EventTypeId mockEvent1Id;
extern StateTypeId mockIntStateId; extern StateTypeId mockIntStateId;
@ -53,6 +54,10 @@ private slots:
void getSupportedDevices_data(); void getSupportedDevices_data();
void getSupportedDevices(); void getSupportedDevices();
void addConfiguredDevice_data();
void addConfiguredDevice();
void getConfiguredDevices(); void getConfiguredDevices();
void executeAction_data(); void executeAction_data();
@ -87,6 +92,10 @@ private:
void TestJSONRPC::initTestcase() void TestJSONRPC::initTestcase()
{ {
// If testcase asserts cleanup won't do. Lets clear any previous test run settings leftovers
QSettings settings;
settings.clear();
QCoreApplication::instance()->setOrganizationName("guh-test"); QCoreApplication::instance()->setOrganizationName("guh-test");
m_commandId = 0; m_commandId = 0;
@ -119,7 +128,7 @@ void TestJSONRPC::initTestcase()
void TestJSONRPC::cleanupTestCase() void TestJSONRPC::cleanupTestCase()
{ {
QSettings settings; QSettings settings;
settings.clear(); // settings.clear();
} }
QVariant TestJSONRPC::injectAndWait(const QString &method, const QVariantMap &params = QVariantMap()) QVariant TestJSONRPC::injectAndWait(const QString &method, const QVariantMap &params = QVariantMap())
@ -241,8 +250,8 @@ void TestJSONRPC::getSupportedDevices_data()
QTest::addColumn<VendorId>("vendorId"); QTest::addColumn<VendorId>("vendorId");
QTest::addColumn<int>("resultCount"); QTest::addColumn<int>("resultCount");
QTest::newRow("vendor guh") << guhVendorId << 1; QTest::newRow("vendor guh") << guhVendorId << 2;
QTest::newRow("no filter") << VendorId() << 1; QTest::newRow("no filter") << VendorId() << 2;
QTest::newRow("invalid vendor") << VendorId("93e7d361-8025-4354-b17e-b68406c800bc") << 0; QTest::newRow("invalid vendor") << VendorId("93e7d361-8025-4354-b17e-b68406c800bc") << 0;
} }
@ -261,7 +270,43 @@ void TestJSONRPC::getSupportedDevices()
QCOMPARE(supportedDevices.toMap().value("params").toMap().value("deviceClasses").toList().count(), resultCount); QCOMPARE(supportedDevices.toMap().value("params").toMap().value("deviceClasses").toList().count(), resultCount);
if (resultCount > 0) { if (resultCount > 0) {
QString deviceName = supportedDevices.toMap().value("params").toMap().value("deviceClasses").toList().first().toMap().value("name").toString(); QString deviceName = supportedDevices.toMap().value("params").toMap().value("deviceClasses").toList().first().toMap().value("name").toString();
QCOMPARE(deviceName, QString("Mock Device")); QVERIFY(deviceName.startsWith(QString("Mock Device")));
}
}
void TestJSONRPC::addConfiguredDevice_data()
{
QTest::addColumn<DeviceClassId>("deviceClassId");
QTest::addColumn<QVariantMap>("deviceParams");
QTest::addColumn<bool>("success");
QVariantMap deviceParams;
deviceParams.insert("httpport", mockDevice1Port - 1);
QTest::newRow("User, JustAdd") << mockDeviceClassId << deviceParams << true;
QTest::newRow("Auto, JustAdd") << mockDeviceAutoClassId << deviceParams << false;
}
void TestJSONRPC::addConfiguredDevice()
{
QFETCH(DeviceClassId, deviceClassId);
QFETCH(QVariantMap, deviceParams);
QFETCH(bool, success);
QVariantMap params;
params.insert("deviceClassId", deviceClassId);
params.insert("deviceParams", deviceParams);
QVariant response = injectAndWait("Devices.AddConfiguredDevice", params);
qDebug() << "response is" << response;
QCOMPARE(response.toMap().value("status").toString(), QString("success"));
QCOMPARE(response.toMap().value("params").toMap().value("success").toBool(), success);
if (success) {
QUuid deviceId(response.toMap().value("params").toMap().value("deviceId").toString());
params.clear();
params.insert("deviceId", deviceId.toString());
injectAndWait("Devices.RemoveConfiguredDevice", params);
QCOMPARE(response.toMap().value("params").toMap().value("success").toBool(), true);
} }
} }
@ -270,7 +315,7 @@ void TestJSONRPC::getConfiguredDevices()
QVariant response = injectAndWait("Devices.GetConfiguredDevices"); QVariant response = injectAndWait("Devices.GetConfiguredDevices");
QVariantList devices = response.toMap().value("params").toMap().value("devices").toList(); QVariantList devices = response.toMap().value("params").toMap().value("devices").toList();
QCOMPARE(devices.count(), 1); QCOMPARE(devices.count(), 2); // There should be one auto created mock device and the one created in initTestcase()
} }
void TestJSONRPC::executeAction_data() void TestJSONRPC::executeAction_data()
@ -478,6 +523,10 @@ void TestJSONRPC::stateChangeEmitsNotifications()
void TestJSONRPC::removeDevice() void TestJSONRPC::removeDevice()
{ {
QVERIFY(!m_mockDeviceId.isNull()); QVERIFY(!m_mockDeviceId.isNull());
QSettings settings;
settings.beginGroup(m_mockDeviceId.toString());
// Make sure we have some config values for this device
QVERIFY(settings.allKeys().count() > 0);
QVariantMap params; QVariantMap params;
params.insert("deviceId", m_mockDeviceId); params.insert("deviceId", m_mockDeviceId);
@ -487,7 +536,6 @@ void TestJSONRPC::removeDevice()
QCOMPARE(response.toMap().value("params").toMap().value("success").toBool(), true); QCOMPARE(response.toMap().value("params").toMap().value("success").toBool(), true);
// Make sure the device is gone from settings too // Make sure the device is gone from settings too
QSettings settings;
QCOMPARE(settings.allKeys().count(), 0); QCOMPARE(settings.allKeys().count(), 0);
} }

View File

@ -1,7 +1,11 @@
#!/bin/bash #!/bin/bash
if [ -z $4 ]; then if [ -z $3 ]; then
echo "usage: $0 host actionTypeId deviceId power" echo "usage: $0 host actionTypeId deviceId [paramname paramvalue]"
elif [ -z $4 ]; then
(echo '{"id":1, "method":"Actions.ExecuteAction","params":{"actionTypeId": "{'$2'}", "deviceId":"{'$3'}"}'; sleep 1) | nc $1 1234
elif [ -z $5 ]; then
echo "usage: $0 host actionTypeId deviceId [paramname paramvalue]"
else else
(echo '{"id":1, "method":"Actions.ExecuteAction","params":{"actionTypeId": "{'$2'}", "deviceId":"{'$3'}","params":{"power":"'$4'"}}}'; sleep 1) | nc $1 1234 (echo '{"id":1, "method":"Actions.ExecuteAction","params":{"actionTypeId": "{'$2'}", "deviceId":"{'$3'}","params":{"'$4'":"'$5'"}}}'; sleep 1) | nc $1 1234
fi fi

View File

@ -1,7 +0,0 @@
#!/bin/bash
if [ -z $3 ]; then
echo "usage: $0 host deviceId stateTypeId"
else
(echo '{"id":1, "method":"Devices.GetDeviceState", "params":{"deviceId":"'$2'", "stateTypeId":"'$3'"}}'; sleep 1) | nc $1 1234
fi

7
tests/scripts/getstatevalue.sh Executable file
View File

@ -0,0 +1,7 @@
#!/bin/bash
if [ -z $3 ]; then
echo "usage: $0 host deviceId stateTypeId"
else
(echo '{"id":1, "method":"Devices.GetStateValue", "params":{"deviceId":"'$2'", "stateTypeId":"'$3'"}}'; sleep 1) | nc $1 1234
fi

View File

@ -2,6 +2,8 @@
if [ -z $1 ]; then if [ -z $1 ]; then
echo "usage $0 host" echo "usage $0 host"
else elif [ -z $2 ]; then
(echo '{"id":1, "method":"Devices.GetSupportedDevices"}'; sleep 1) | nc $1 1234 (echo '{"id":1, "method":"Devices.GetSupportedDevices"}'; sleep 1) | nc $1 1234
else
(echo '{"id":1, "method":"Devices.GetSupportedDevices", "params":{"vendorId":"'$2'"}}'; sleep 1) | nc $1 1234
fi fi

View File

@ -1,7 +1,11 @@
#!/bin/bash #!/bin/bash
if [ -z $1 ]; then if [ -z $4 ]; then
echo "usage $0 host" echo "usage $0 host pluginid param1name param1value [param2name param2value]"
elif [ -z $5 ]; then
(echo '{"id":1, "method":"Devices.SetPluginConfiguration", "params":{"pluginId":"'$2'", "pluginParams":{"'$3'":"'$4'"}}}'; sleep 1) | nc $1 1234
elif [ -z $6 ]; then
echo "usage $0 host pluginid param1name param1value [param2name param2value]"
else else
(echo '{"id":1, "method":"Devices.SetPluginConfig", "params":{"pluginId":"'$2'", "params":{"foo":"bar"}}}'; sleep 1) | nc $1 1234 (echo '{"id":1, "method":"Devices.SetPluginConfiguration", "params":{"pluginId":"'$2'", "pluginParams":{"'$3'":"'$4'", "'$5'":"'$6'"}}}'; sleep 1) | nc $1 1234
fi fi