diff --git a/genericinterfaces/deviceplugingenericinterfaces.cpp b/genericinterfaces/deviceplugingenericinterfaces.cpp
new file mode 100644
index 00000000..b88ebb6d
--- /dev/null
+++ b/genericinterfaces/deviceplugingenericinterfaces.cpp
@@ -0,0 +1,158 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * *
+ * Copyright (C) 2019 Bernhard Trinnes . *
+ * *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*!
+ \page genericinterfaces.html
+ \title Generic interfaces
+ \brief Common interfaces to test the rule engine.
+
+ \ingroup plugins
+ \ingroup nymea-tests
+
+ The generic interfaces plugin allows you create virtual buttons, which can be connected with a rule. This gives you
+ the possibility to execute multiple \l{Action}{Actions} with one signal. Without a rule this generic interfaces are
+ useless.
+
+ \chapter Plugin properties
+ Following JSON file contains the definition and the description of all available \l{DeviceClass}{DeviceClasses}
+ and \l{Vendor}{Vendors} of this \l{DevicePlugin}.
+
+ For more details how to read this JSON file please check out the documentation for \l{The plugin JSON File}.
+
+ \quotefile plugins/deviceplugins/genericinterfaces/deviceplugingenericinterfaces.json
+*/
+
+
+#include "deviceplugingenericinterfaces.h"
+#include "devicemanager.h"
+#include "plugininfo.h"
+
+#include
+
+DevicePluginGenericInterfaces::DevicePluginGenericInterfaces()
+{
+}
+
+DeviceManager::DeviceSetupStatus DevicePluginGenericInterfaces::setupDevice(Device *device)
+{
+ if (device->deviceClassId() == awningDeviceClassId) {
+ return DeviceManager::DeviceSetupStatusSuccess;
+ }
+
+ if (device->deviceClassId() == blindDeviceClassId) {
+ return DeviceManager::DeviceSetupStatusSuccess;
+ }
+
+ if (device->deviceClassId() == shutterDeviceClassId) {
+ return DeviceManager::DeviceSetupStatusSuccess;
+ }
+
+ if (device->deviceClassId() == socketDeviceClassId) {
+ return DeviceManager::DeviceSetupStatusSuccess;
+ }
+
+ if (device->deviceClassId() == lightDeviceClassId) {
+ return DeviceManager::DeviceSetupStatusSuccess;
+ }
+
+ if (device->deviceClassId() == heatingDeviceClassId) {
+ return DeviceManager::DeviceSetupStatusSuccess;
+ }
+ return DeviceManager::DeviceSetupStatusFailure;
+}
+
+DeviceManager::DeviceError DevicePluginGenericInterfaces::executeAction(Device *device, const Action &action)
+{
+ if (device->deviceClassId() == awningDeviceClassId) {
+ if (action.actionTypeId() == awningOpenActionTypeId) {
+ return DeviceManager::DeviceErrorNoError;
+ }
+ if (action.actionTypeId() == awningStopActionTypeId) {
+ return DeviceManager::DeviceErrorNoError;
+ }
+ if (action.actionTypeId() == awningCloseActionTypeId) {
+ return DeviceManager::DeviceErrorNoError;
+ }
+ return DeviceManager::DeviceErrorActionTypeNotFound;
+ }
+
+ if (device->deviceClassId() == blindDeviceClassId ) {
+ if (action.actionTypeId() == blindOpenActionTypeId) {
+ return DeviceManager::DeviceErrorNoError;
+ }
+ if (action.actionTypeId() == blindStopActionTypeId) {
+ return DeviceManager::DeviceErrorNoError;
+ }
+ if (action.actionTypeId() == blindCloseActionTypeId) {
+ return DeviceManager::DeviceErrorNoError;
+ }
+ return DeviceManager::DeviceErrorActionTypeNotFound;
+ }
+
+ if (device->deviceClassId() == shutterDeviceClassId) {
+ if (action.actionTypeId() == shutterOpenActionTypeId) {
+ return DeviceManager::DeviceErrorNoError;
+ }
+ if (action.actionTypeId() == shutterStopActionTypeId) {
+ return DeviceManager::DeviceErrorNoError;
+ }
+ if (action.actionTypeId() == shutterCloseActionTypeId) {
+ return DeviceManager::DeviceErrorNoError;
+ }
+ return DeviceManager::DeviceErrorActionTypeNotFound;
+ }
+
+ if (device->deviceClassId() == awningDeviceClassId) {
+ if (action.actionTypeId() == awningOpenActionTypeId) {
+ return DeviceManager::DeviceErrorNoError;
+ }
+ if (action.actionTypeId() == awningStopActionTypeId) {
+ return DeviceManager::DeviceErrorNoError;
+ }
+ if (action.actionTypeId() == awningCloseActionTypeId) {
+ return DeviceManager::DeviceErrorNoError;
+ }
+ return DeviceManager::DeviceErrorActionTypeNotFound;
+ }
+
+ if (device->deviceClassId() == socketDeviceClassId) {
+ if (action.actionTypeId() == socketPowerActionTypeId) {
+ return DeviceManager::DeviceErrorNoError;
+ }
+ return DeviceManager::DeviceErrorActionTypeNotFound;
+ }
+
+ if (device->deviceClassId() == lightDeviceClassId) {
+ if (action.actionTypeId() == lightPowerActionTypeId) {
+ return DeviceManager::DeviceErrorNoError;
+ }
+ return DeviceManager::DeviceErrorActionTypeNotFound;
+ }
+
+ if (device->deviceClassId() == heatingDeviceClassId) {
+ if (action.actionTypeId() == heatingPowerActionTypeId) {
+ return DeviceManager::DeviceErrorNoError;
+ }
+ return DeviceManager::DeviceErrorActionTypeNotFound;
+ }
+ return DeviceManager::DeviceErrorDeviceClassNotFound;
+}
diff --git a/genericinterfaces/deviceplugingenericinterfaces.h b/genericinterfaces/deviceplugingenericinterfaces.h
new file mode 100644
index 00000000..a7ed4a82
--- /dev/null
+++ b/genericinterfaces/deviceplugingenericinterfaces.h
@@ -0,0 +1,44 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * *
+ * Copyright (C) 2019 Bernhard Trinnes . *
+ * *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+#ifndef DEVICEPLUGINGENERICINTERFACES_H
+#define DEVICEPLUGINGENERICINTERFACES_H
+
+#include "plugin/deviceplugin.h"
+
+class DevicePluginGenericInterfaces : public DevicePlugin
+{
+ Q_OBJECT
+
+ Q_PLUGIN_METADATA(IID "io.nymea.DevicePlugin" FILE "deviceplugingenericinterfaces.json")
+ Q_INTERFACES(DevicePlugin)
+
+public:
+ explicit DevicePluginGenericInterfaces();
+ DeviceManager::DeviceSetupStatus setupDevice(Device *device) override;
+
+public slots:
+ DeviceManager::DeviceError executeAction(Device *device, const Action &action) override;
+
+};
+
+#endif // DEVICEPLUGINGENERICINTERFACES_H
diff --git a/genericinterfaces/deviceplugingenericinterfaces.json b/genericinterfaces/deviceplugingenericinterfaces.json
new file mode 100644
index 00000000..9f1c5ac7
--- /dev/null
+++ b/genericinterfaces/deviceplugingenericinterfaces.json
@@ -0,0 +1,143 @@
+{
+ "name": "GenericInterfaces",
+ "displayName": "Generic Interfaces",
+ "id": "b3188696-2585-4806-bf98-30ab576ce5c8",
+ "vendors": [
+ {
+ "name": "nymea",
+ "displayName": "nymea",
+ "id": "2062d64d-3232-433c-88bc-0d33c0ba2ba6",
+ "deviceClasses": [
+ {
+ "id": "",
+ "name": "awning",
+ "displayName": "Awning",
+ "createMethods": ["user"],
+ "interfaces": ["awning"],
+ "actionTypes": [
+ {
+ "id": "979e9c51-5a93-4635-85e3-01874306b229",
+ "name": "open",
+ "displayName": "Open"
+ },
+ {
+ "id": "555cafe4-bd12-42c6-bab1-8cd59af6468e",
+ "name": "stop",
+ "displayName": "stop"
+ },
+ {
+ "id": "53b5ba77-9a34-4cd6-ad24-fb01fc465f98",
+ "name": "close",
+ "displayName": "close"
+ }
+ ]
+ },
+ {
+ "id": "17ee3657-6ad8-4ae2-8959-3cf66cec8d13",
+ "name": "blind",
+ "displayName": "Blind",
+ "createMethods": ["user"],
+ "interfaces": ["blind"],
+ "actionTypes": [
+ {
+ "id": "120dc265-dbbb-4f19-9d31-c372c23479c0",
+ "name": "open",
+ "displayName": "Open"
+ },
+ {
+ "id": "1a924c9a-5dcb-4b1c-8fd6-ab101098e007",
+ "name": "stop",
+ "displayName": "stop"
+ },
+ {
+ "id": "86e9cf21-7487-47c4-b4be-4a940d7235fb",
+ "name": "close",
+ "displayName": "close"
+ }
+ ]
+ },
+ {
+ "id": "7917c2e7-d7d2-4c47-a38d-41f7dd7693d9",
+ "name": "shutter",
+ "displayName": "Shutter",
+ "createMethods": ["user"],
+ "interfaces": ["shutter"],
+ "actionTypes": [
+ {
+ "id": "9deb662d-2378-4345-a898-8742d41e43c1",
+ "name": "open",
+ "displayName": "Open"
+ },
+ {
+ "id": "db5f3332-1f4e-4f9e-84d2-93c5d7de315c",
+ "name": "stop",
+ "displayName": "stop"
+ },
+ {
+ "id": "cf5303f1-67c7-4cef-b11c-eb9de6fc8a87",
+ "name": "close",
+ "displayName": "close"
+ }
+ ]
+ },
+ {
+ "id": "4e7261af-a27b-4446-8346-914ea59f7547",
+ "name": "socket",
+ "displayName": "Socket",
+ "createMethods": ["user"],
+ "interfaces": ["powersocket"],
+ "stateTypes": [
+ {
+ "id": "018038d7-1d02-4b17-8fe3-babca044b087",
+ "name": "power",
+ "displayName": "Power",
+ "displayNameEvent": "Power changed",
+ "displayNameAction": "Set power",
+ "type": "bool",
+ "defaultValue": false,
+ "writable": true
+ }
+ ]
+ },
+ {
+ "id": "c50d3216-f307-4f9f-8190-4391510c385c",
+ "name": "light",
+ "displayName": "Light",
+ "createMethods": ["user"],
+ "interfaces": ["light"],
+ "stateTypes": [
+ {
+ "id": "8b6e4a67-6522-408b-b676-8d2f09ed2d54",
+ "name": "power",
+ "displayName": "Power",
+ "displayNameEvent": "Power changed",
+ "displayNameAction": "Set power",
+ "type": "bool",
+ "defaultValue": false,
+ "writable": true
+ }
+ ]
+ },
+ {
+ "id": "392854c4-3d14-4cf8-96cd-d933526bd197",
+ "name": "heating",
+ "displayName": "Heating",
+ "createMethods": ["user"],
+ "interfaces": ["heating"],
+ "stateTypes": [
+ {
+ "id": "409b635e-a754-4b5c-b3f0-d1c5a0fb3f03",
+ "name": "power",
+ "displayName": "Power",
+ "displayNameEvent": "Power changed",
+ "displayNameAction": "Set power",
+ "type": "bool",
+ "defaultValue": false,
+ "writable": true
+ }
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/genericinterfaces/genericinterfaces.pro b/genericinterfaces/genericinterfaces.pro
new file mode 100644
index 00000000..d66633dd
--- /dev/null
+++ b/genericinterfaces/genericinterfaces.pro
@@ -0,0 +1,12 @@
+include(../plugins.pri)
+
+TARGET = $$qtLibraryTarget(nymea_deviceplugingenericinterfaces)
+
+SOURCES += \
+ deviceplugingenericinterfaces.cpp
+
+HEADERS += \
+ deviceplugingenericinterfaces.h
+
+
+
diff --git a/genericinterfaces/translations/b3188696-2585-4806-bf98-30ab576ce5c8-en_US.ts b/genericinterfaces/translations/b3188696-2585-4806-bf98-30ab576ce5c8-en_US.ts
new file mode 100644
index 00000000..f7f66d85
--- /dev/null
+++ b/genericinterfaces/translations/b3188696-2585-4806-bf98-30ab576ce5c8-en_US.ts
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/nymea-plugins.pro b/nymea-plugins.pro
index 8985227c..b682ed0e 100644
--- a/nymea-plugins.pro
+++ b/nymea-plugins.pro
@@ -16,6 +16,7 @@ PLUGIN_DIRS = \
eq-3 \
flowercare \
genericelements \
+ genericinterfaces \
gpio \
httpcommander \
intertechno \