diff --git a/debian/guh-plugins.install b/debian/guh-plugins.install
index 58f93046..e321b7ee 100644
--- a/debian/guh-plugins.install
+++ b/debian/guh-plugins.install
@@ -14,3 +14,5 @@ usr/lib/guh/plugins/libguh_deviceplugindatetime.so
usr/lib/guh/plugins/libguh_deviceplugingenericelements.so
usr/lib/guh/plugins/libguh_deviceplugincommandlauncher.so
usr/lib/guh/plugins/libguh_devicepluginunitec.so
+usr/lib/guh/plugins/libguh_devicepluginleynew.so
+usr/lib/guh/plugins/libguh_deviceplugintune.so
diff --git a/plugins/deviceplugins/deviceplugins.pro b/plugins/deviceplugins/deviceplugins.pro
index 4b9f4b19..94dae701 100644
--- a/plugins/deviceplugins/deviceplugins.pro
+++ b/plugins/deviceplugins/deviceplugins.pro
@@ -14,6 +14,8 @@ SUBDIRS += elro \
genericelements \
commandlauncher \
unitec \
+ leynew \
+ tune \
diff --git a/plugins/deviceplugins/tune/deviceplugintune.cpp b/plugins/deviceplugins/tune/deviceplugintune.cpp
new file mode 100644
index 00000000..5f91ebc8
--- /dev/null
+++ b/plugins/deviceplugins/tune/deviceplugintune.cpp
@@ -0,0 +1,165 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * *
+ * This file is part of guh. *
+ * *
+ * Guh is free software: you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation, version 2 of the License. *
+ * *
+ * Guh is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with guh. If not, see . *
+ * *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+#include
+#include
+#include
+
+#include "deviceplugintune.h"
+#include "devicemanager.h"
+#include "plugininfo.h"
+
+DevicePluginTune::DevicePluginTune()
+{
+ m_manager = new TuneManager(31337, this);
+
+ connect(m_manager, &TuneManager::tuneConnectionStatusChanged, this, &DevicePluginTune::tuneConnectionStatusChanged);
+ connect(m_manager, &TuneManager::dataReady, this, &DevicePluginTune::tuneDataAvailable);
+
+ m_manager->start();
+}
+
+DeviceManager::HardwareResources DevicePluginTune::requiredHardware() const
+{
+ return DeviceManager::HardwareResourceNone;
+}
+
+DeviceManager::DeviceSetupStatus DevicePluginTune::setupDevice(Device *device)
+{
+ if (!m_manager->tuneAvailable()) {
+ qWarning() << "WARNING: tune not connected!";
+ }
+
+ // check index position
+ int position = device->paramValue("position").toInt();
+ if (position >= myDevices().count()) {
+ device->setParamValue("position", myDevices().count());
+ } else {
+ foreach (Device *d, myDevices()) {
+ int currentPosition = d->paramValue("position").toInt();
+ if (currentPosition >= position) {
+ d->setParamValue("position", currentPosition + 1);
+ }
+ }
+ }
+
+ // mood
+ if (device->deviceClassId() == moodDeviceClassId) {
+ device->setName(device->paramValue("name").toString() + " (Mood)");
+ return DeviceManager::DeviceSetupStatusSuccess;
+ }
+
+ // todo
+ if (device->deviceClassId() == todoDeviceClassId) {
+ device->setName(device->paramValue("name").toString() + " (Todo)");
+ return DeviceManager::DeviceSetupStatusSuccess;
+ }
+
+ return DeviceManager::DeviceSetupStatusFailure;
+}
+
+void DevicePluginTune::deviceRemoved(Device *device)
+{
+ int position = device->paramValue("position").toInt();
+
+ foreach (Device *d, myDevices()) {
+ int currentPosition = d->paramValue("position").toInt();
+ if (currentPosition >= position ) {
+ d->setParamValue("position", currentPosition - 1);
+ }
+ }
+ sync();
+}
+
+bool DevicePluginTune::sync()
+{
+ // sync with devices with tune
+ if (!m_manager->tuneAvailable()) {
+ return false;
+ }
+
+ QVariantMap message;
+ QVariantList devices;
+ foreach (Device* device, myDevices()) {
+ qDebug() << "device id" << device->id();
+ QVariantMap d;
+ d.insert("name", device->paramValue("name"));
+ d.insert("id", device->id());
+ d.insert("deviceClassId", device->deviceClassId());
+ d.insert("pos", device->paramValue("position"));
+ d.insert("icon", device->paramValue("icon"));
+ devices.append(d);
+ }
+ message.insert("devices", devices);
+
+ QJsonDocument jsonDoc = QJsonDocument::fromVariant(message);
+ QByteArray data = jsonDoc.toJson(QJsonDocument::Compact);
+
+ qDebug() << data;
+
+ m_manager->sendData(data);
+
+ return true;
+}
+
+void DevicePluginTune::tuneConnectionStatusChanged(const bool &connected)
+{
+ if (connected) {
+ sync();
+ }
+}
+
+void DevicePluginTune::tuneDataAvailable(const QByteArray &data)
+{
+ QJsonParseError error;
+ QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &error);
+
+ if(error.error != QJsonParseError::NoError) {
+ qDebug() << "failed to parse data" << data << ":" << error.errorString();
+ }
+ qDebug() << jsonDoc.toJson();
+
+}
+
+DeviceManager::DeviceError DevicePluginTune::executeAction(Device *device, const Action &action)
+{
+ if (!m_manager->tuneAvailable()) {
+ return DeviceManager::DeviceErrorHardwareNotAvailable;
+ }
+
+ // Mood
+ if (device->deviceClassId() == moodDeviceClassId) {
+ if (action.actionTypeId() == toggleActionTypeId) {
+ bool currentState = device->stateValue(activeStateTypeId).toBool();
+ device->setStateValue(activeStateTypeId, !currentState);
+ return DeviceManager::DeviceErrorNoError;
+ }
+ return DeviceManager::DeviceErrorActionTypeNotFound;
+ }
+
+ // Todo
+ if (device->deviceClassId() == todoDeviceClassId) {
+ if (action.actionTypeId() == pressActionTypeId) {
+ emit emitEvent(Event(pressedEventTypeId, device->id()));
+ return DeviceManager::DeviceErrorNoError;
+ }
+ }
+
+ return DeviceManager::DeviceErrorDeviceClassNotFound;
+}
+
diff --git a/plugins/deviceplugins/tune/deviceplugintune.h b/plugins/deviceplugins/tune/deviceplugintune.h
new file mode 100644
index 00000000..708fc056
--- /dev/null
+++ b/plugins/deviceplugins/tune/deviceplugintune.h
@@ -0,0 +1,52 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * *
+ * This file is part of guh. *
+ * *
+ * Guh is free software: you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation, version 2 of the License. *
+ * *
+ * Guh is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with guh. If not, see . *
+ * *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+#ifndef DEVICEPLUGINTUNE_H
+#define DEVICEPLUGINTUNE_H
+
+#include "plugin/deviceplugin.h"
+#include "tunemanager.h"
+
+class DevicePluginTune : public DevicePlugin
+{
+ Q_OBJECT
+
+ Q_PLUGIN_METADATA(IID "guru.guh.DevicePlugin" FILE "deviceplugintune.json")
+ Q_INTERFACES(DevicePlugin)
+
+public:
+ explicit DevicePluginTune();
+
+ DeviceManager::HardwareResources requiredHardware() const override;
+ DeviceManager::DeviceSetupStatus setupDevice(Device *device) override;
+ void deviceRemoved(Device *device) override;
+
+private:
+ TuneManager *m_manager;
+ bool sync();
+
+private slots:
+ void tuneConnectionStatusChanged(const bool &connected);
+ void tuneDataAvailable(const QByteArray &data);
+
+public slots:
+ DeviceManager::DeviceError executeAction(Device *device, const Action &action) override;
+
+};
+
+#endif // DEVICEPLUGINTUNE_H
diff --git a/plugins/deviceplugins/tune/deviceplugintune.json b/plugins/deviceplugins/tune/deviceplugintune.json
new file mode 100644
index 00000000..11966d17
--- /dev/null
+++ b/plugins/deviceplugins/tune/deviceplugintune.json
@@ -0,0 +1,142 @@
+{
+ "name": "Tune",
+ "id": "826c8f4a-e2e1-4891-84d4-2c7a46ab1eea",
+ "vendors": [
+ {
+ "name": "Tune",
+ "id": "9ba2d9dc-b975-46bb-9e83-dbbd03ccab6c",
+ "deviceClasses": [
+ {
+ "deviceClassId": "a5bd9e14-c169-416b-9b60-9453b1403a97",
+ "idName": "mood",
+ "name": "Mood",
+ "createMethods": ["user"],
+ "paramTypes": [
+ {
+ "name": "name",
+ "type": "QString",
+ "inputType": "TextLine"
+ },
+ {
+ "name": "position",
+ "type": "int"
+ },
+ {
+ "name": "icon",
+ "type": "QString",
+ "allowedValues": [
+ "IconCouch",
+ "IconWork",
+ "IconToilet",
+ "IconSex",
+ "IconDrinking",
+ "IconEating",
+ "IconSmoking"
+ ]
+ }
+ ],
+ "stateTypes": [
+ {
+ "id": "535ed312-16de-47f2-bf3a-5661f7b86a42",
+ "idName": "active",
+ "name": "active",
+ "type": "bool",
+ "defaultValue": false
+ },
+ {
+ "id": "cb8a89c2-dc12-4965-b047-57896058b421",
+ "idName": "value",
+ "name": "value",
+ "type": "uint",
+ "defaultValue": 50
+ }
+ ],
+ "actionTypes": [
+ {
+ "id": "768b6a17-731b-4976-bc9e-15c04eff7df3",
+ "idName": "toggle",
+ "name": "toggle"
+ },
+ {
+ "id": "fe942f70-b8fb-413b-8feb-2dd924b9f649",
+ "idName": "setValue",
+ "name": "set value",
+ "paramTypes": [
+ {
+ "name": "percentage",
+ "type": "uint",
+ "minimumValue": 0,
+ "maximumValue": 100
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "deviceClassId": "56c14ef8-3a19-432f-9d9f-dc7e1d489312",
+ "idName": "todo",
+ "name": "ToDo",
+ "createMethods": ["user"],
+ "paramTypes": [
+ {
+ "name": "name",
+ "type": "QString",
+ "inputType": "TextLine"
+ },
+ {
+ "name": "position",
+ "type": "int"
+ },
+ {
+ "name": "icon",
+ "type": "QString",
+ "allowedValues": [
+ "IconCouch",
+ "IconWork",
+ "IconToilet",
+ "IconSex",
+ "IconDrinking",
+ "IconEating",
+ "IconSmoking"
+ ]
+ }
+ ],
+ "eventTypes": [
+ {
+ "id": "52b66edc-df40-42ef-a39c-aa2b77fdf42e",
+ "idName": "pressed",
+ "name": "pressed"
+ },
+ {
+ "id": "277f10fd-3fc3-4229-904a-661b6f1cac54",
+ "idName": "todoLeft",
+ "name": "left"
+ },
+ {
+ "id": "a510968e-f313-4880-95bd-786bd3bcb357",
+ "idName": "todoRight",
+ "name": "right"
+ }
+ ],
+ "actionTypes": [
+ {
+ "id": "1a2dac4d-26b3-496f-a4c2-8cb90c75e026",
+ "idName": "press",
+ "name": "press"
+ },
+ {
+ "id": "0c461c5a-1334-4559-816b-73b5b2afb3ba",
+ "idName": "tickLeft",
+ "name": "tick left"
+ },
+ {
+ "id": "a67cda4a-2c6f-4815-818a-08094dfcc453",
+ "idName": "tickRight",
+ "name": "tick right"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/plugins/deviceplugins/tune/tune.pro b/plugins/deviceplugins/tune/tune.pro
new file mode 100644
index 00000000..5e11d9a5
--- /dev/null
+++ b/plugins/deviceplugins/tune/tune.pro
@@ -0,0 +1,13 @@
+include(../../plugins.pri)
+
+TARGET = $$qtLibraryTarget(guh_deviceplugintune)
+
+SOURCES += \
+ deviceplugintune.cpp \
+ tunemanager.cpp
+
+HEADERS += \
+ deviceplugintune.h \
+ tunemanager.h
+
+
diff --git a/plugins/deviceplugins/tune/tunemanager.cpp b/plugins/deviceplugins/tune/tunemanager.cpp
new file mode 100644
index 00000000..e65a2a32
--- /dev/null
+++ b/plugins/deviceplugins/tune/tunemanager.cpp
@@ -0,0 +1,117 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * *
+ * This file is part of guh. *
+ * *
+ * Guh is free software: you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation, version 2 of the License. *
+ * *
+ * Guh is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with guh. If not, see . *
+ * *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+#include "tunemanager.h"
+
+TuneManager::TuneManager(int port, QObject *parent) :
+ QObject(parent),
+ m_server(0),
+ m_tune(0),
+ m_port(port),
+ m_connected(false)
+{
+}
+
+bool TuneManager::tuneAvailable()
+{
+ return m_connected;
+}
+
+bool TuneManager::sendData(const QByteArray &data)
+{
+ if (m_connected) {
+ m_tune->write(data + '\n');
+ return true;
+ }
+ return false;
+}
+
+void TuneManager::tuneConnected()
+{
+
+
+ QTcpSocket *socket = m_server->nextPendingConnection();
+
+ if (m_tune) {
+ qWarning() << "--> ATTENTION: tune allready connected! connection refused.";
+ socket->disconnect();
+ delete socket;
+ return;
+ }
+
+ m_tune = socket;
+
+ connect(m_tune, &QTcpSocket::readyRead, this, &TuneManager::readData);
+ connect(m_tune, &QTcpSocket::disconnected, this, &TuneManager::tuneDisconnected);
+
+ qDebug() << " --> tune connected:" << m_tune->peerAddress().toString() << m_port;
+ m_connected = true;
+ emit tuneConnectionStatusChanged(true);
+}
+
+void TuneManager::tuneDisconnected()
+{
+ qWarning() << " --> tune disconnected:" << m_tune->peerAddress().toString();
+ m_connected = false;
+ emit tuneConnectionStatusChanged(false);
+ delete m_tune;
+ m_tune = 0;
+}
+
+void TuneManager::readData()
+{
+ QByteArray message;
+ while (m_tune->canReadLine()) {
+ QByteArray dataLine = m_tune->readLine();
+ qDebug() << " --> tune line in:" << dataLine;
+ message.append(dataLine);
+ if (dataLine.endsWith('\n')) {
+ emit dataReady(message);
+ message.clear();
+ }
+ }
+}
+
+bool TuneManager::start()
+{
+ if(!m_server) {
+ m_server = new QTcpServer(this);
+ }
+
+ m_server->setMaxPendingConnections(1);
+
+ QHostAddress localhost = QHostAddress(QHostAddress::LocalHost);
+ if(!m_server->listen(localhost, m_port)) {
+ qWarning() << "ERROR: Tune server can not listen on" << localhost << m_port;
+ delete m_server;
+ return false;
+ }
+ qDebug() << " --> Tune server started" << localhost << m_port;
+ connect(m_server, &QTcpServer::newConnection, this, &TuneManager::tuneConnected);
+ return true;
+}
+
+void TuneManager::stop()
+{
+ qDebug() << " --> close Tune server" << m_server->serverAddress().toString();
+ m_server->close();
+ delete m_server;
+ m_server = 0;
+ m_connected = false;
+ emit tuneConnectionStatusChanged(false);
+}
diff --git a/plugins/deviceplugins/tune/tunemanager.h b/plugins/deviceplugins/tune/tunemanager.h
new file mode 100644
index 00000000..f462984c
--- /dev/null
+++ b/plugins/deviceplugins/tune/tunemanager.h
@@ -0,0 +1,59 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * *
+ * This file is part of guh. *
+ * *
+ * Guh is free software: you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation, version 2 of the License. *
+ * *
+ * Guh is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with guh. If not, see . *
+ * *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+#ifndef TUNEMANAGER_H
+#define TUNEMANAGER_H
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+class TuneManager : public QObject
+{
+ Q_OBJECT
+public:
+ explicit TuneManager(int port = 31337, QObject *parent = 0);
+
+ bool tuneAvailable();
+ bool sendData(const QByteArray &data);
+
+private:
+ QTcpServer *m_server;
+ QTcpSocket *m_tune;
+
+ int m_port;
+ int m_connected;
+
+signals:
+ void dataReady(const QByteArray &data);
+ void tuneConnectionStatusChanged(const bool &connectionStatus);
+
+private slots:
+ void tuneConnected();
+ void tuneDisconnected();
+ void readData();
+
+public slots:
+ bool start();
+ void stop();
+};
+
+#endif // TUNEMANAGER_H