From 8d1c7f9c030e668c95fb84cefbb8dfb8f41aacd4 Mon Sep 17 00:00:00 2001 From: Michael Zanetti Date: Sun, 13 Apr 2014 10:27:08 +0200 Subject: [PATCH] add createmethod and setupmethod params add support for createmethod "auto" add functional boblight plugin --- libguh/devicemanager.cpp | 87 ++++++++--- libguh/devicemanager.h | 18 ++- libguh/plugin/deviceclass.cpp | 24 ++- libguh/plugin/deviceclass.h | 19 +++ libguh/plugin/deviceplugin.cpp | 22 +++ libguh/plugin/deviceplugin.h | 5 +- libguh/typeutils.h | 1 + plugins/deviceplugins/boblight/bobclient.cpp | 107 ++++++++++++++ plugins/deviceplugins/boblight/bobclient.h | 40 +++++ plugins/deviceplugins/boblight/boblight.pro | 17 +++ .../boblight/devicepluginboblight.cpp | 138 ++++++++++++++++++ .../boblight/devicepluginboblight.h | 43 ++++++ .../boblight/devicepluginboblight.json | 1 + .../conrad/devicepluginconrad.cpp | 4 +- .../deviceplugins/conrad/devicepluginconrad.h | 2 +- plugins/deviceplugins/deviceplugins.pro | 4 +- .../deviceplugins/elro/devicepluginelro.cpp | 3 +- plugins/deviceplugins/elro/devicepluginelro.h | 2 +- .../intertechno/devicepluginintertechno.cpp | 8 +- .../intertechno/devicepluginintertechno.h | 2 +- .../deviceplugins/mock/devicepluginmock.cpp | 33 ++++- plugins/deviceplugins/mock/devicepluginmock.h | 4 +- server/jsonrpc/actionhandler.cpp | 10 +- server/jsonrpc/devicehandler.cpp | 20 ++- server/jsonrpc/devicehandler.h | 2 +- server/jsonrpc/jsontypes.cpp | 32 ++++ server/jsonrpc/jsontypes.h | 4 + server/main.cpp | 1 + server/ruleengine.cpp | 3 - server/server.pro | 4 + tests/auto/testjsonrpc.cpp | 60 +++++++- tests/scripts/executeaction.sh | 10 +- tests/scripts/getdevicestate.sh | 7 - tests/scripts/getstatevalue.sh | 7 + tests/scripts/getsupporteddevices.sh | 4 +- tests/scripts/setpluginconfig.sh | 10 +- 36 files changed, 686 insertions(+), 72 deletions(-) create mode 100644 plugins/deviceplugins/boblight/bobclient.cpp create mode 100644 plugins/deviceplugins/boblight/bobclient.h create mode 100644 plugins/deviceplugins/boblight/boblight.pro create mode 100644 plugins/deviceplugins/boblight/devicepluginboblight.cpp create mode 100644 plugins/deviceplugins/boblight/devicepluginboblight.h create mode 100644 plugins/deviceplugins/boblight/devicepluginboblight.json delete mode 100755 tests/scripts/getdevicestate.sh create mode 100755 tests/scripts/getstatevalue.sh diff --git a/libguh/devicemanager.cpp b/libguh/devicemanager.cpp index 155ae092..8a6fa391 100644 --- a/libguh/devicemanager.cpp +++ b/libguh/devicemanager.cpp @@ -100,6 +100,7 @@ DeviceManager::DeviceManager(QObject *parent) : // Give hardware a chance to start up before loading plugins etc. QMetaObject::invokeMethod(this, "loadPlugins", 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 QMetaObject::invokeMethod(this, "loaded", Qt::QueuedConnection); } @@ -111,11 +112,20 @@ QList DeviceManager::plugins() const } /*! 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); } +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 DeviceManager::supportedVendors() const { return m_supportedVendors.values(); @@ -142,6 +152,19 @@ QList DeviceManager::supportedDevices(const VendorId &vendorId) con be generated. */ DeviceManager::DeviceError DeviceManager::addConfiguredDevice(const DeviceClassId &deviceClassId, const QVariantMap ¶ms, 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 ¶ms, const DeviceId id) { DeviceClass deviceClass = findDeviceClass(deviceClassId); if (deviceClass.id().isNull()) { @@ -182,7 +205,7 @@ DeviceManager::DeviceError DeviceManager::addConfiguredDevice(const DeviceClassI return DeviceErrorNoError; } -DeviceManager::DeviceError DeviceManager::removeConfiguredDevice(const QUuid &deviceId) +DeviceManager::DeviceError DeviceManager::removeConfiguredDevice(const DeviceId &deviceId) { Device *device = findConfiguredDevice(deviceId); 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. */ -Device *DeviceManager::findConfiguredDevice(const QUuid &id) const +Device *DeviceManager::findConfiguredDevice(const DeviceId &id) const { foreach (Device *device, m_configuredDevices) { if (device->id() == id) { @@ -224,7 +247,7 @@ QList DeviceManager::configuredDevices() const } /*! Returns all \l{Device}{Devices} matching the \l{DeviceClass} referred by \a deviceClassId. */ -QList DeviceManager::findConfiguredDevices(const QUuid &deviceClassId) const +QList DeviceManager::findConfiguredDevices(const DeviceClassId &deviceClassId) const { QList ret; foreach (Device *device, m_configuredDevices) { @@ -235,19 +258,6 @@ QList DeviceManager::findConfiguredDevices(const QUuid &deviceClassId) 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. Note: The returned DeviceClass may be invalid.*/ DeviceClass DeviceManager::findDeviceClass(const QUuid &deviceClassId) const @@ -275,14 +285,19 @@ DeviceManager::DeviceError DeviceManager::executeAction(const Action &action) foreach (const ActionType &actionType, deviceClass.actions()) { if (actionType.id() == action.actionTypeId()) { found = true; + + if (actionType.parameters().count() > action.params().count()) { + return DeviceErrorMissingParameter; + } + + continue; } } if (!found) { return DeviceErrorActionTypeNotFound; } - m_devicePlugins.value(device->pluginId())->executeAction(device, action); - return DeviceErrorNoError; + return m_devicePlugins.value(device->pluginId())->executeAction(device, action); } } return DeviceErrorDeviceNotFound; @@ -313,6 +328,11 @@ void DeviceManager::loadPlugins() m_supportedDevices.insert(deviceClass.id(), deviceClass); 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); 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 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) { Device *device = qobject_cast(sender()); diff --git a/libguh/devicemanager.h b/libguh/devicemanager.h index 523954e7..265b479e 100644 --- a/libguh/devicemanager.h +++ b/libguh/devicemanager.h @@ -53,23 +53,27 @@ public: DeviceErrorMissingParameter, DeviceErrorPluginNotFound, DeviceErrorSetupFailed, - DeviceErrorDuplicateUuid + DeviceErrorDuplicateUuid, + DeviceErrorCreationNotSupported, + DeviceErrorDeviceParameterError, + DeviceErrorActionParameterError }; explicit DeviceManager(QObject *parent = 0); QList plugins() const; - DevicePlugin* plugin(const QUuid &id) const; + DevicePlugin* plugin(const PluginId &id) const; + void setPluginConfig(const PluginId &pluginId, const QVariantMap &pluginConfig); + QList supportedVendors() const; QList supportedDevices(const VendorId &vendorId = VendorId()) const; QList configuredDevices() const; DeviceError addConfiguredDevice(const DeviceClassId &deviceClassId, const QVariantMap ¶ms, const DeviceId id = DeviceId::createDeviceId()); - DeviceError removeConfiguredDevice(const QUuid &deviceId); + DeviceError removeConfiguredDevice(const DeviceId &deviceId); - Device* findConfiguredDevice(const QUuid &id) const; - QList findConfiguredDevices(const QUuid &deviceClassId) const; - DeviceClass findDeviceClassforEvent(const QUuid &eventTypeId) const; + Device* findConfiguredDevice(const DeviceId &id) const; + QList findConfiguredDevices(const DeviceClassId &deviceClassId) const; DeviceClass findDeviceClass(const QUuid &deviceClassId) const; signals: @@ -84,6 +88,7 @@ private slots: void loadPlugins(); void loadConfiguredDevices(); void storeConfiguredDevices(); + void createNewAutoDevices(); // Only connect this to Devices. It will query the sender() void slotDeviceStateValueChanged(const QUuid &stateTypeId, const QVariant &value); @@ -92,6 +97,7 @@ private slots: void timerEvent(); private: + DeviceError addConfiguredDeviceInternal(const DeviceClassId &deviceClassId, const QVariantMap ¶ms, const DeviceId id = DeviceId::createDeviceId()); bool setupDevice(Device *device); QHash m_supportedVendors; diff --git a/libguh/plugin/deviceclass.cpp b/libguh/plugin/deviceclass.cpp index ebf7fb26..b7544235 100644 --- a/libguh/plugin/deviceclass.cpp +++ b/libguh/plugin/deviceclass.cpp @@ -42,7 +42,9 @@ DeviceClass::DeviceClass(const QUuid &pluginId, const VendorId &vendorId, const DeviceClassId &id): m_id(id), m_vendorId(vendorId), - m_pluginId(pluginId) + m_pluginId(pluginId), + m_createMethod(CreateMethodUser), + m_setupMethod(SetupMethodJustAdd) { } @@ -139,6 +141,26 @@ void DeviceClass::setParams(const QVariantList ¶ms) 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.*/ bool DeviceClass::operator==(const DeviceClass &deviceClass) const { diff --git a/libguh/plugin/deviceclass.h b/libguh/plugin/deviceclass.h index 905c535f..d2b7e32d 100644 --- a/libguh/plugin/deviceclass.h +++ b/libguh/plugin/deviceclass.h @@ -31,6 +31,18 @@ class DeviceClass { 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()); DeviceClassId id() const; @@ -53,6 +65,11 @@ public: QVariantList params() const; void setParams(const QVariantList ¶ms); + CreateMethod createMethod() const; + void setCreateMethod(CreateMethod createMethod); + SetupMethod setupMethod() const; + void setSetupMethod(SetupMethod setupMethod); + bool operator==(const DeviceClass &device) const; private: @@ -64,6 +81,8 @@ private: QList m_events; QList m_actions; QVariantList m_params; + CreateMethod m_createMethod; + SetupMethod m_setupMethod; }; #endif diff --git a/libguh/plugin/deviceplugin.cpp b/libguh/plugin/deviceplugin.cpp index 6883f96c..f3cab22f 100644 --- a/libguh/plugin/deviceplugin.cpp +++ b/libguh/plugin/deviceplugin.cpp @@ -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 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. Return false if something bad happened during the setup. The device will be disabled. */ diff --git a/libguh/plugin/deviceplugin.h b/libguh/plugin/deviceplugin.h index 3202154e..62ba519c 100644 --- a/libguh/plugin/deviceplugin.h +++ b/libguh/plugin/deviceplugin.h @@ -22,6 +22,7 @@ #include "devicemanager.h" #include "deviceclass.h" +#include "typeutils.h" #include "types/event.h" #include "types/action.h" #include "types/vendor.h" @@ -47,6 +48,8 @@ public: virtual QList supportedDevices() const = 0; virtual DeviceManager::HardwareResources requiredHardware() const = 0; + virtual bool configureAutoDevice(QList loadedDevices, Device *device) const; + virtual bool deviceCreated(Device *device); virtual void deviceRemoved(Device *device); @@ -58,7 +61,7 @@ public: virtual void setConfiguration(const QVariantMap &configuration); 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: diff --git a/libguh/typeutils.h b/libguh/typeutils.h index 0f30c628..59f54752 100644 --- a/libguh/typeutils.h +++ b/libguh/typeutils.h @@ -22,6 +22,7 @@ DECLARE_TYPE_ID(Device) DECLARE_TYPE_ID(EventType) DECLARE_TYPE_ID(StateType) DECLARE_TYPE_ID(ActionType) +DECLARE_TYPE_ID(Plugin) #endif // TYPEUTILS_H diff --git a/plugins/deviceplugins/boblight/bobclient.cpp b/plugins/deviceplugins/boblight/bobclient.cpp new file mode 100644 index 00000000..019b6e6f --- /dev/null +++ b/plugins/deviceplugins/boblight/bobclient.cpp @@ -0,0 +1,107 @@ +#include "bobclient.h" + +#include "libboblight/boblight.h" + +#include + +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]; +} diff --git a/plugins/deviceplugins/boblight/bobclient.h b/plugins/deviceplugins/boblight/bobclient.h new file mode 100644 index 00000000..8e02041f --- /dev/null +++ b/plugins/deviceplugins/boblight/bobclient.h @@ -0,0 +1,40 @@ +#ifndef BOBCLIENT_H +#define BOBCLIENT_H + +#include +#include +#include +#include +#include + +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 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 diff --git a/plugins/deviceplugins/boblight/boblight.pro b/plugins/deviceplugins/boblight/boblight.pro new file mode 100644 index 00000000..bc4ea13f --- /dev/null +++ b/plugins/deviceplugins/boblight/boblight.pro @@ -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 \ + + + diff --git a/plugins/deviceplugins/boblight/devicepluginboblight.cpp b/plugins/deviceplugins/boblight/devicepluginboblight.cpp new file mode 100644 index 00000000..938f039c --- /dev/null +++ b/plugins/deviceplugins/boblight/devicepluginboblight.cpp @@ -0,0 +1,138 @@ +#include "devicepluginboblight.h" + +#include "plugin/device.h" +#include "devicemanager.h" + +#include "bobclient.h" + +#include +#include + +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 DevicePluginBoblight::supportedVendors() const +{ + QList ret; + Vendor guh(boblightVendorId, "http://code.google.com/p/boblight/"); + ret.append(guh); + return ret; +} + +QList DevicePluginBoblight::supportedDevices() const +{ + QList ret; + + DeviceClass deviceClassBoblight(pluginId(), boblightVendorId, boblightDeviceClassId); + deviceClassBoblight.setName("Boblight"); + deviceClassBoblight.setCreateMethod(DeviceClass::CreateMethodAuto); + + QList boblightStates; + + StateType colorState(colorStateTypeId); + colorState.setName("color"); + colorState.setType(QVariant::Color); + colorState.setDefaultValue(QColor(Qt::black)); + boblightStates.append(colorState); + + deviceClassBoblight.setStates(boblightStates); + + QList 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 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(); + 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()); +} diff --git a/plugins/deviceplugins/boblight/devicepluginboblight.h b/plugins/deviceplugins/boblight/devicepluginboblight.h new file mode 100644 index 00000000..fdf22751 --- /dev/null +++ b/plugins/deviceplugins/boblight/devicepluginboblight.h @@ -0,0 +1,43 @@ +#ifndef DEVICEPLUGINBOBLIGHT_H +#define DEVICEPLUGINBOBLIGHT_H + +#include "plugin/deviceplugin.h" + +#include + +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 supportedVendors() const override; + QList supportedDevices() const override; + DeviceManager::HardwareResources requiredHardware() const override; + + bool configureAutoDevice(QList 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 diff --git a/plugins/deviceplugins/boblight/devicepluginboblight.json b/plugins/deviceplugins/boblight/devicepluginboblight.json new file mode 100644 index 00000000..0967ef42 --- /dev/null +++ b/plugins/deviceplugins/boblight/devicepluginboblight.json @@ -0,0 +1 @@ +{} diff --git a/plugins/deviceplugins/conrad/devicepluginconrad.cpp b/plugins/deviceplugins/conrad/devicepluginconrad.cpp index 0432379c..cd3fe3e8 100644 --- a/plugins/deviceplugins/conrad/devicepluginconrad.cpp +++ b/plugins/deviceplugins/conrad/devicepluginconrad.cpp @@ -124,13 +124,13 @@ QUuid DevicePluginConrad::pluginId() const 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 rawData; QByteArray binCode; - + return DeviceManager::DeviceErrorNoError; } void DevicePluginConrad::radioData(QList rawData) diff --git a/plugins/deviceplugins/conrad/devicepluginconrad.h b/plugins/deviceplugins/conrad/devicepluginconrad.h index 21019071..0ee4c433 100644 --- a/plugins/deviceplugins/conrad/devicepluginconrad.h +++ b/plugins/deviceplugins/conrad/devicepluginconrad.h @@ -41,7 +41,7 @@ public: void radioData(QList rawData) override; public slots: - void executeAction(Device *device, const Action &action) override; + DeviceManager::DeviceError executeAction(Device *device, const Action &action) override; }; diff --git a/plugins/deviceplugins/deviceplugins.pro b/plugins/deviceplugins/deviceplugins.pro index 078a0651..3736dc7a 100644 --- a/plugins/deviceplugins/deviceplugins.pro +++ b/plugins/deviceplugins/deviceplugins.pro @@ -8,4 +8,6 @@ SUBDIRS += elro \ # weatherground \ openweathermap \ -# boblight \ +boblight { + SUBDIRS += boblight +} diff --git a/plugins/deviceplugins/elro/devicepluginelro.cpp b/plugins/deviceplugins/elro/devicepluginelro.cpp index 721dbe24..7bbccd09 100644 --- a/plugins/deviceplugins/elro/devicepluginelro.cpp +++ b/plugins/deviceplugins/elro/devicepluginelro.cpp @@ -221,7 +221,7 @@ QUuid DevicePluginElro::pluginId() const 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 rawData; @@ -314,6 +314,7 @@ void DevicePluginElro::executeAction(Device *device, const Action &action) //qDebug() << "rawData" << rawData; qDebug() << "transmit" << pluginName() << action.params().value("power").toBool(); transmitData(rawData); + return DeviceManager::DeviceErrorNoError; } void DevicePluginElro::radioData(QList rawData) diff --git a/plugins/deviceplugins/elro/devicepluginelro.h b/plugins/deviceplugins/elro/devicepluginelro.h index 5910222f..ea29d161 100644 --- a/plugins/deviceplugins/elro/devicepluginelro.h +++ b/plugins/deviceplugins/elro/devicepluginelro.h @@ -41,7 +41,7 @@ public: void radioData(QList rawData) override; public slots: - void executeAction(Device *device, const Action &action) override; + DeviceManager::DeviceError executeAction(Device *device, const Action &action) override; }; diff --git a/plugins/deviceplugins/intertechno/devicepluginintertechno.cpp b/plugins/deviceplugins/intertechno/devicepluginintertechno.cpp index d60e61af..aa376932 100644 --- a/plugins/deviceplugins/intertechno/devicepluginintertechno.cpp +++ b/plugins/deviceplugins/intertechno/devicepluginintertechno.cpp @@ -357,7 +357,7 @@ QUuid DevicePluginIntertechno::pluginId() const 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 rawData; @@ -400,7 +400,7 @@ void DevicePluginIntertechno::executeAction(Device *device, const Action &action }else if(familyCode == "P"){ binCode.append("01010101"); }else{ - return; + return DeviceManager::DeviceErrorDeviceParameterError; } QString buttonCode = device->params().value("buttonCode").toString(); @@ -440,7 +440,7 @@ void DevicePluginIntertechno::executeAction(Device *device, const Action &action }else if(familyCode == "16"){ binCode.append("01010101"); }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(); transmitData(rawData); + return DeviceManager::DeviceErrorNoError; + } void DevicePluginIntertechno::radioData(QList rawData) diff --git a/plugins/deviceplugins/intertechno/devicepluginintertechno.h b/plugins/deviceplugins/intertechno/devicepluginintertechno.h index 6cd95f57..2535e267 100644 --- a/plugins/deviceplugins/intertechno/devicepluginintertechno.h +++ b/plugins/deviceplugins/intertechno/devicepluginintertechno.h @@ -41,7 +41,7 @@ public: void radioData(QList rawData) override; public slots: - void executeAction(Device *device, const Action &action) override; + DeviceManager::DeviceError executeAction(Device *device, const Action &action) override; }; diff --git a/plugins/deviceplugins/mock/devicepluginmock.cpp b/plugins/deviceplugins/mock/devicepluginmock.cpp index 7c814e15..838733ce 100644 --- a/plugins/deviceplugins/mock/devicepluginmock.cpp +++ b/plugins/deviceplugins/mock/devicepluginmock.cpp @@ -27,6 +27,7 @@ VendorId guhVendorId = VendorId("2062d64d-3232-433c-88bc-0d33c0ba2ba6"); 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 mockEvent2Id = EventTypeId("863d5920-b1cf-4eb9-88bd-8f7b8583b1cf"); StateTypeId mockIntStateId = StateTypeId("80baec19-54de-4948-ac46-31eabfaceb83"); @@ -103,6 +104,19 @@ QList DevicePluginMock::supportedDevices() const 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; } @@ -144,7 +158,24 @@ void DevicePluginMock::deviceRemoved(Device *device) m_daemons.take(device)->deleteLater(); } -void DevicePluginMock::executeAction(Device *device, const Action &action) +bool DevicePluginMock::configureAutoDevice(QList 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(); m_daemons.value(device)->actionExecuted(action.actionTypeId()); diff --git a/plugins/deviceplugins/mock/devicepluginmock.h b/plugins/deviceplugins/mock/devicepluginmock.h index e4db1804..0028dd5a 100644 --- a/plugins/deviceplugins/mock/devicepluginmock.h +++ b/plugins/deviceplugins/mock/devicepluginmock.h @@ -45,8 +45,10 @@ public: bool deviceCreated(Device *device) override; void deviceRemoved(Device *device) override; + bool configureAutoDevice(QList loadedDevices, Device *device) const override; + public slots: - void executeAction(Device *device, const Action &action) override; + DeviceManager::DeviceError executeAction(Device *device, const Action &action) override; private slots: void setState(const StateTypeId &stateTypeId, const QVariant &value); diff --git a/server/jsonrpc/actionhandler.cpp b/server/jsonrpc/actionhandler.cpp index 1acde003..93234eea 100644 --- a/server/jsonrpc/actionhandler.cpp +++ b/server/jsonrpc/actionhandler.cpp @@ -68,8 +68,16 @@ QVariantMap ActionHandler::ExecuteAction(const QVariantMap ¶ms) returns.insert("errorMessage", "No such device"); returns.insert("success", false); 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: - returns.insert("errorMessage", "Unknown error."); + returns.insert("errorMessage", QString("Unknown error %1").arg(error)); returns.insert("success", false); } diff --git a/server/jsonrpc/devicehandler.cpp b/server/jsonrpc/devicehandler.cpp index c7868b58..c324fe8a 100644 --- a/server/jsonrpc/devicehandler.cpp +++ b/server/jsonrpc/devicehandler.cpp @@ -57,13 +57,13 @@ DeviceHandler::DeviceHandler(QObject *parent) : setReturns("GetPlugins", returns); params.clear(); returns.clear(); - setDescription("SetPluginParams", "Set a plugin's params."); + setDescription("SetPluginConfiguration", "Set a plugin's params."); params.insert("pluginId", "uuid"); QVariantList pluginParams; pluginParams.append(JsonTypes::paramTypeRef()); params.insert("pluginParams", pluginParams); - setParams("SetPluginParams", params); - setReturns("SetPluginParams", returns); + setParams("SetPluginConfiguration", params); + setReturns("SetPluginConfiguration", returns); params.clear(); returns.clear(); setDescription("AddConfiguredDevice", "Add a configured device."); @@ -190,11 +190,11 @@ QVariantMap DeviceHandler::GetPlugins(const QVariantMap ¶ms) const return returns; } -QVariantMap DeviceHandler::SetPluginParams(const QVariantMap ¶ms) +QVariantMap DeviceHandler::SetPluginConfiguration(const QVariantMap ¶ms) { - QUuid pluginId = params.value("pluginId").toUuid(); + PluginId pluginId = PluginId(params.value("pluginId").toString()); QVariantMap pluginParams = params.value("pluginParams").toMap(); - GuhCore::instance()->deviceManager()->plugin(pluginId)->setConfiguration(pluginParams); + GuhCore::instance()->deviceManager()->setPluginConfig(pluginId, pluginParams); return QVariantMap(); } @@ -223,6 +223,10 @@ QVariantMap DeviceHandler::AddConfiguredDevice(const QVariantMap ¶ms) returns.insert("errorMessage", "Error creating device. Device setup failed."); returns.insert("success", false); break; + case DeviceManager::DeviceErrorCreationNotSupported: + returns.insert("errorMessage", "Error creating device. This device can't be created this way."); + returns.insert("success", false); + break; default: returns.insert("errorMessage", "Unknown error."); returns.insert("success", false); @@ -245,7 +249,7 @@ QVariantMap DeviceHandler::GetConfiguredDevices(const QVariantMap ¶ms) const QVariantMap DeviceHandler::RemoveConfiguredDevice(const QVariantMap ¶ms) { QVariantMap returns; - switch(GuhCore::instance()->deviceManager()->removeConfiguredDevice(params.value("deviceId").toUuid())) { + switch(GuhCore::instance()->deviceManager()->removeConfiguredDevice(DeviceId(params.value("deviceId").toString()))) { case DeviceManager::DeviceErrorNoError: returns.insert("success", true); returns.insert("errorMessage", ""); @@ -303,7 +307,7 @@ QVariantMap DeviceHandler::GetStateValue(const QVariantMap ¶ms) const { 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) { returns.insert("success", false); returns.insert("errorMessage", "No such device"); diff --git a/server/jsonrpc/devicehandler.h b/server/jsonrpc/devicehandler.h index 9123688e..bebd9640 100644 --- a/server/jsonrpc/devicehandler.h +++ b/server/jsonrpc/devicehandler.h @@ -35,7 +35,7 @@ public: Q_INVOKABLE QVariantMap GetPlugins(const QVariantMap ¶ms) const; - Q_INVOKABLE QVariantMap SetPluginParams(const QVariantMap ¶ms); + Q_INVOKABLE QVariantMap SetPluginConfiguration(const QVariantMap ¶ms); Q_INVOKABLE QVariantMap AddConfiguredDevice(const QVariantMap ¶ms); diff --git a/server/jsonrpc/jsontypes.cpp b/server/jsonrpc/jsontypes.cpp index 4ac9ec04..ebfe137d 100644 --- a/server/jsonrpc/jsontypes.cpp +++ b/server/jsonrpc/jsontypes.cpp @@ -29,6 +29,8 @@ QString JsonTypes::s_lastError; QVariantList JsonTypes::s_basicTypes; QVariantList JsonTypes::s_ruleTypes; +QVariantList JsonTypes::s_createMethodTypes; +QVariantList JsonTypes::s_setupMethodTypes; QVariantMap JsonTypes::s_paramType; QVariantMap JsonTypes::s_param; @@ -49,6 +51,8 @@ void JsonTypes::init() // BasicTypes s_basicTypes << "uuid" << "string" << "integer" << "double" << "bool"; s_ruleTypes << "RuleTypeMatchAll" << "RuleTypeMatchAny"; + s_createMethodTypes << "CreateMethodUser" << "CreateMethodAuto" << "CreateMethodDiscovery"; + s_setupMethodTypes << "SetupMethodJustAdd" << "SetupMethodDisplayPin" << "SetupMethodEnterPin" << "SetupMethodPushButton"; // ParamType s_paramType.insert("name", "string"); @@ -107,6 +111,8 @@ void JsonTypes::init() s_deviceClass.insert("events", QVariantList() << eventTypeRef()); s_deviceClass.insert("actions", QVariantList() << actionTypeRef()); s_deviceClass.insert("params", QVariantList() << paramTypeRef()); + s_deviceClass.insert("setupMethod", setupMethodTypesRef()); + s_deviceClass.insert("createMethod", createMethodTypesRef()); // Device s_device.insert("id", "uuid"); @@ -133,6 +139,8 @@ QVariantMap JsonTypes::allTypes() QVariantMap allTypes; allTypes.insert("BasicType", basicTypes()); allTypes.insert("ParamType", paramTypeDescription()); + allTypes.insert("CreateMethodType", createMethodTypes()); + allTypes.insert("SetupMethodType", setupMethodTypes()); allTypes.insert("StateType", stateTypeDescription()); allTypes.insert("EventType", eventTypeDescription()); allTypes.insert("ActionType", actionTypeDescription()); @@ -224,6 +232,8 @@ QVariantMap JsonTypes::packDeviceClass(const DeviceClass &deviceClass) variant.insert("states", stateTypes); variant.insert("events", eventTypes); variant.insert("actions", actionTypes); + variant.insert("createMethod", s_createMethodTypes.at(deviceClass.createMethod())); + variant.insert("setupMethod", s_setupMethodTypes.at(deviceClass.setupMethod())); return variant; } @@ -406,6 +416,18 @@ QPair JsonTypes::validateVariant(const QVariant &templateVariant, qDebug() << "value not allowed in" << ruleTypesRef(); return result; } + } else if (refName == createMethodTypesRef()) { + QPair result = validateCreateMethodType(variant); + if (!result.first) { + qDebug() << "value not allowed in" << createMethodTypesRef(); + return result; + } + } else if (refName == setupMethodTypesRef()) { + QPair result = validateSetupMethodType(variant); + if (!result.first) { + qDebug() << "value not allowed in" << createMethodTypesRef(); + return result; + } } else { qDebug() << "unhandled ref:" << refName; return report(false, QString("Unhandled ref %1. Server implementation incomplete.").arg(refName)); @@ -464,3 +486,13 @@ QPair JsonTypes::validateRuleType(const QVariant &variant) { return report(s_ruleTypes.contains(variant.toString()), QString("Unknown rules type %1").arg(variant.toString())); } + +QPair JsonTypes::validateCreateMethodType(const QVariant &variant) +{ + return report(s_createMethodTypes.contains(variant.toString()), QString("Unknwon createMethod type %1").arg(variant.toString())); +} + +QPair JsonTypes::validateSetupMethodType(const QVariant &variant) +{ + return report(s_setupMethodTypes.contains(variant.toString()), QString("Unknwon setupMethod type %1").arg(variant.toString())); +} diff --git a/server/jsonrpc/jsontypes.h b/server/jsonrpc/jsontypes.h index 96bf5c94..6acea032 100644 --- a/server/jsonrpc/jsontypes.h +++ b/server/jsonrpc/jsontypes.h @@ -63,6 +63,8 @@ public: DECLARE_TYPE(basicTypes, "BasicType") DECLARE_TYPE(ruleTypes, "RuleType") + DECLARE_TYPE(createMethodTypes, "CreateMethodType") + DECLARE_TYPE(setupMethodTypes, "SetupMethodType") DECLARE_OBJECT(paramType, "ParamType") DECLARE_OBJECT(param, "Param") DECLARE_OBJECT(stateType, "StateType") @@ -94,6 +96,8 @@ public: static QPair validateVariant(const QVariant &templateVariant, const QVariant &variant); static QPair validateBasicType(const QVariant &variant); static QPair validateRuleType(const QVariant &variant); + static QPair validateCreateMethodType(const QVariant &variant); + static QPair validateSetupMethodType(const QVariant &variant); private: static bool s_initialized; diff --git a/server/main.cpp b/server/main.cpp index 6a76b446..dbdc2559 100644 --- a/server/main.cpp +++ b/server/main.cpp @@ -29,6 +29,7 @@ Q_IMPORT_PLUGIN(DevicePluginConrad) Q_IMPORT_PLUGIN(DevicePluginMock) //Q_IMPORT_PLUGIN(DevicePluginWeatherground) Q_IMPORT_PLUGIN(DevicePluginOpenweathermap) +Q_IMPORT_PLUGIN(DevicePluginBoblight) int main(int argc, char *argv[]) { diff --git a/server/ruleengine.cpp b/server/ruleengine.cpp index 8834448d..5cf67329 100644 --- a/server/ruleengine.cpp +++ b/server/ruleengine.cpp @@ -156,9 +156,6 @@ RuleEngine::RuleError RuleEngine::addRule(const Event &event, const QList &states, const QList &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()); if (!device) { qWarning() << "Cannot create rule. No configured device for eventTypeId" << event.eventTypeId(); diff --git a/server/server.pro b/server/server.pro index ce020391..3d4ef9df 100644 --- a/server/server.pro +++ b/server/server.pro @@ -23,3 +23,7 @@ LIBS += -L../plugins/deviceplugins/conrad -lguh_devicepluginconrad LIBS += -L../plugins/deviceplugins/mock -lguh_devicepluginmock #LIBS += -L../plugins/deviceplugins/weatherground -lguh_devicepluginweatherground LIBS += -L../plugins/deviceplugins/openweathermap -lguh_devicepluginopenweathermap + +boblight { + LIBS += -L../plugins/deviceplugins/boblight -lguh_devicepluginboblight -L/usr/local/lib/ -lboblight +} diff --git a/tests/auto/testjsonrpc.cpp b/tests/auto/testjsonrpc.cpp index 718611c7..78282ae9 100644 --- a/tests/auto/testjsonrpc.cpp +++ b/tests/auto/testjsonrpc.cpp @@ -34,6 +34,7 @@ int mockDevice2Port = 7331; extern VendorId guhVendorId; extern DeviceClassId mockDeviceClassId; +extern DeviceClassId mockDeviceAutoClassId; extern ActionTypeId mockAction1Id; extern EventTypeId mockEvent1Id; extern StateTypeId mockIntStateId; @@ -53,6 +54,10 @@ private slots: void getSupportedDevices_data(); void getSupportedDevices(); + + void addConfiguredDevice_data(); + void addConfiguredDevice(); + void getConfiguredDevices(); void executeAction_data(); @@ -87,6 +92,10 @@ private: 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"); m_commandId = 0; @@ -119,7 +128,7 @@ void TestJSONRPC::initTestcase() void TestJSONRPC::cleanupTestCase() { QSettings settings; - settings.clear(); +// settings.clear(); } QVariant TestJSONRPC::injectAndWait(const QString &method, const QVariantMap ¶ms = QVariantMap()) @@ -241,8 +250,8 @@ void TestJSONRPC::getSupportedDevices_data() QTest::addColumn("vendorId"); QTest::addColumn("resultCount"); - QTest::newRow("vendor guh") << guhVendorId << 1; - QTest::newRow("no filter") << VendorId() << 1; + QTest::newRow("vendor guh") << guhVendorId << 2; + QTest::newRow("no filter") << VendorId() << 2; 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); if (resultCount > 0) { 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"); + QTest::addColumn("deviceParams"); + QTest::addColumn("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"); 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() @@ -478,6 +523,10 @@ void TestJSONRPC::stateChangeEmitsNotifications() void TestJSONRPC::removeDevice() { 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; params.insert("deviceId", m_mockDeviceId); @@ -487,7 +536,6 @@ void TestJSONRPC::removeDevice() QCOMPARE(response.toMap().value("params").toMap().value("success").toBool(), true); // Make sure the device is gone from settings too - QSettings settings; QCOMPARE(settings.allKeys().count(), 0); } diff --git a/tests/scripts/executeaction.sh b/tests/scripts/executeaction.sh index c269839c..d5f4438e 100755 --- a/tests/scripts/executeaction.sh +++ b/tests/scripts/executeaction.sh @@ -1,7 +1,11 @@ #!/bin/bash -if [ -z $4 ]; then - echo "usage: $0 host actionTypeId deviceId power" +if [ -z $3 ]; then + 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 - (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 diff --git a/tests/scripts/getdevicestate.sh b/tests/scripts/getdevicestate.sh deleted file mode 100755 index 727bddbf..00000000 --- a/tests/scripts/getdevicestate.sh +++ /dev/null @@ -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 diff --git a/tests/scripts/getstatevalue.sh b/tests/scripts/getstatevalue.sh new file mode 100755 index 00000000..b80e5d5d --- /dev/null +++ b/tests/scripts/getstatevalue.sh @@ -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 diff --git a/tests/scripts/getsupporteddevices.sh b/tests/scripts/getsupporteddevices.sh index c717ef5c..c9533aee 100755 --- a/tests/scripts/getsupporteddevices.sh +++ b/tests/scripts/getsupporteddevices.sh @@ -2,6 +2,8 @@ if [ -z $1 ]; then echo "usage $0 host" -else +elif [ -z $2 ]; then (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 diff --git a/tests/scripts/setpluginconfig.sh b/tests/scripts/setpluginconfig.sh index 047f25c7..6cadfb6a 100755 --- a/tests/scripts/setpluginconfig.sh +++ b/tests/scripts/setpluginconfig.sh @@ -1,7 +1,11 @@ #!/bin/bash -if [ -z $1 ]; then - echo "usage $0 host" +if [ -z $4 ]; then + 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 - (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