added denon plug-in
This commit is contained in:
parent
0eafc2f0fb
commit
78183f48a8
2
debian/guh-plugins.install
vendored
2
debian/guh-plugins.install
vendored
@ -19,3 +19,5 @@ usr/lib/guh/plugins/libguh_devicepluginkodi.so
|
|||||||
usr/lib/guh/plugins/libguh_devicepluginelgato.so
|
usr/lib/guh/plugins/libguh_devicepluginelgato.so
|
||||||
usr/lib/guh/plugins/libguh_devicepluginawattar.so
|
usr/lib/guh/plugins/libguh_devicepluginawattar.so
|
||||||
usr/lib/guh/plugins/libguh_devicepluginnetatmo.so
|
usr/lib/guh/plugins/libguh_devicepluginnetatmo.so
|
||||||
|
usr/lib/guh/plugins/libguh_deviceplugindenon.so
|
||||||
|
|
||||||
|
|||||||
194
plugins/deviceplugins/denon/denon.cpp
Normal file
194
plugins/deviceplugins/denon/denon.cpp
Normal file
@ -0,0 +1,194 @@
|
|||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
* *
|
||||||
|
* Copyright (C) 2015 Simon Stuerz <simon.stuerz@guh.guru> *
|
||||||
|
* Copyright (C) 2016 Bernhard Trinnes <bernhard.trinnes@guh.guru> *
|
||||||
|
* *
|
||||||
|
* 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 <http://www.gnu.org/licenses/>. *
|
||||||
|
* *
|
||||||
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
d
|
||||||
|
#include "denon.h"
|
||||||
|
|
||||||
|
Kodi::Kodi(const QHostAddress &hostAddress, const int &port, QObject *parent) :
|
||||||
|
QObject(parent),
|
||||||
|
m_muted(false),
|
||||||
|
m_volume(-1)
|
||||||
|
{
|
||||||
|
m_connection = new KodiConnection(hostAddress, port, this);
|
||||||
|
connect (m_connection, &KodiConnection::connectionStatusChanged, this, &Kodi::connectionStatusChanged);
|
||||||
|
|
||||||
|
m_jsonHandler = new KodiJsonHandler(m_connection, this);
|
||||||
|
connect(m_jsonHandler, &KodiJsonHandler::volumeChanged, this, &Kodi::onVolumeChanged);
|
||||||
|
connect(m_jsonHandler, &KodiJsonHandler::actionExecuted, this, &Kodi::actionExecuted);
|
||||||
|
connect(m_jsonHandler, &KodiJsonHandler::versionDataReceived, this, &Kodi::versionDataReceived);
|
||||||
|
connect(m_jsonHandler, &KodiJsonHandler::updateDataReceived, this, &Kodi::updateDataReceived);
|
||||||
|
connect(m_jsonHandler, &KodiJsonHandler::updateDataReceived, this, &Kodi::onUpdateFinished);
|
||||||
|
connect(m_jsonHandler, &KodiJsonHandler::onPlayerPlay, this, &Kodi::onPlayerPlay);
|
||||||
|
connect(m_jsonHandler, &KodiJsonHandler::onPlayerPause, this, &Kodi::onPlayerPause);
|
||||||
|
connect(m_jsonHandler, &KodiJsonHandler::onPlayerStop, this, &Kodi::onPlayerStop);
|
||||||
|
}
|
||||||
|
|
||||||
|
QHostAddress Kodi::hostAddress() const
|
||||||
|
{
|
||||||
|
return m_connection->hostAddress();
|
||||||
|
}
|
||||||
|
|
||||||
|
int Kodi::port() const
|
||||||
|
{
|
||||||
|
return m_connection->port();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Kodi::connected() const
|
||||||
|
{
|
||||||
|
return m_connection->connected();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Kodi::setMuted(const bool &muted, const ActionId &actionId)
|
||||||
|
{
|
||||||
|
QVariantMap params;
|
||||||
|
params.insert("mute", muted);
|
||||||
|
|
||||||
|
m_jsonHandler->sendData("Application.SetMute", params, actionId);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Kodi::muted() const
|
||||||
|
{
|
||||||
|
return m_muted;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Kodi::setVolume(const int &volume, const ActionId &actionId)
|
||||||
|
{
|
||||||
|
QVariantMap params;
|
||||||
|
params.insert("volume", volume);
|
||||||
|
|
||||||
|
m_jsonHandler->sendData("Application.SetVolume", params, actionId);
|
||||||
|
}
|
||||||
|
|
||||||
|
int Kodi::volume() const
|
||||||
|
{
|
||||||
|
return m_volume;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Kodi::showNotification(const QString &message, const int &displayTime, const QString ¬ificationType, const ActionId &actionId)
|
||||||
|
{
|
||||||
|
QVariantMap params;
|
||||||
|
params.insert("title", "guh notification");
|
||||||
|
params.insert("message", message);
|
||||||
|
params.insert("displaytime", displayTime);
|
||||||
|
params.insert("image", notificationType);
|
||||||
|
|
||||||
|
m_jsonHandler->sendData("GUI.ShowNotification", params, actionId);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Kodi::pressButton(const QString &button, const ActionId &actionId)
|
||||||
|
{
|
||||||
|
QVariantMap params;
|
||||||
|
params.insert("action", button);
|
||||||
|
m_jsonHandler->sendData("Input.ExecuteAction", params, actionId);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Kodi::systemCommand(const QString &command, const ActionId &actionId)
|
||||||
|
{
|
||||||
|
QString method;
|
||||||
|
if (command == "hibernate") {
|
||||||
|
method = "Hibernate";
|
||||||
|
} else if (command == "reboot") {
|
||||||
|
method = "Reboot";
|
||||||
|
} else if (command == "shutdown") {
|
||||||
|
method = "Shutdown";
|
||||||
|
} else if (command == "suspend") {
|
||||||
|
method = "Suspend";
|
||||||
|
} else {
|
||||||
|
// already checkt with allowed values
|
||||||
|
}
|
||||||
|
|
||||||
|
m_jsonHandler->sendData("System." + method, QVariantMap(), actionId);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Kodi::videoLibrary(const QString &command, const ActionId &actionId)
|
||||||
|
{
|
||||||
|
QString method;
|
||||||
|
if (command == "scan") {
|
||||||
|
method = "Scan";
|
||||||
|
} else if (command == "clean") {
|
||||||
|
method = "Clean";
|
||||||
|
} else {
|
||||||
|
// already checkt with allowed values
|
||||||
|
}
|
||||||
|
|
||||||
|
m_jsonHandler->sendData("VideoLibrary." + method, QVariantMap(), actionId);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Kodi::audioLibrary(const QString &command, const ActionId &actionId)
|
||||||
|
{
|
||||||
|
QString method;
|
||||||
|
if (command == "scan") {
|
||||||
|
method = "Scan";
|
||||||
|
} else if (command == "clean") {
|
||||||
|
method = "Clean";
|
||||||
|
} else {
|
||||||
|
// already checkt with allowed values
|
||||||
|
}
|
||||||
|
|
||||||
|
m_jsonHandler->sendData("AudioLibrary." + method, QVariantMap(), actionId);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Kodi::update()
|
||||||
|
{
|
||||||
|
QVariantMap params;
|
||||||
|
QVariantList properties;
|
||||||
|
properties.append("volume");
|
||||||
|
properties.append("muted");
|
||||||
|
properties.append("name");
|
||||||
|
properties.append("version");
|
||||||
|
params.insert("properties", properties);
|
||||||
|
|
||||||
|
m_jsonHandler->sendData("Application.GetProperties", params, ActionId());
|
||||||
|
}
|
||||||
|
|
||||||
|
void Kodi::checkVersion()
|
||||||
|
{
|
||||||
|
m_jsonHandler->sendData("JSONRPC.Version", QVariantMap(), ActionId());
|
||||||
|
}
|
||||||
|
|
||||||
|
void Kodi::connectKodi()
|
||||||
|
{
|
||||||
|
m_connection->connectKodi();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Kodi::disconnectKodi()
|
||||||
|
{
|
||||||
|
m_connection->disconnectKodi();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Kodi::onVolumeChanged(const int &volume, const bool &muted)
|
||||||
|
{
|
||||||
|
if (m_volume != volume || m_muted != muted) {
|
||||||
|
m_volume = volume;
|
||||||
|
m_muted = muted;
|
||||||
|
emit stateChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Kodi::onUpdateFinished(const QVariantMap &data)
|
||||||
|
{
|
||||||
|
if (data.contains("volume")) {
|
||||||
|
m_volume = data.value("volume").toInt();
|
||||||
|
}
|
||||||
|
if (data.contains("muted")) {
|
||||||
|
m_muted = data.value("muted").toBool();
|
||||||
|
}
|
||||||
|
emit stateChanged();
|
||||||
|
}
|
||||||
86
plugins/deviceplugins/denon/denon.h
Normal file
86
plugins/deviceplugins/denon/denon.h
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
|
||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
* *
|
||||||
|
* Copyright (C) 2015 Simon Stuerz <simon.stuerz@guh.guru> *
|
||||||
|
* Copyright (C) 2015 Bernhard Trinnes <bernhard.trinnes@guh.guru> *
|
||||||
|
* *
|
||||||
|
* 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 <http://www.gnu.org/licenses/>. *
|
||||||
|
* *
|
||||||
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
|
#ifndef DENON_H
|
||||||
|
#define DENON_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QHostAddress>
|
||||||
|
|
||||||
|
#include "denonconnection.h"
|
||||||
|
|
||||||
|
class Denon : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
|
||||||
|
explicit Denon(const QHostAddress &hostAddress, const int &port = 9090, QObject *parent = 0);
|
||||||
|
|
||||||
|
QHostAddress hostAddress() const;
|
||||||
|
int port() const;
|
||||||
|
|
||||||
|
bool connected() const;
|
||||||
|
|
||||||
|
// propertys
|
||||||
|
void setMuted(const bool &muted, const ActionId &actionId);
|
||||||
|
bool muted() const;
|
||||||
|
|
||||||
|
void setVolume(const int &volume, const ActionId &actionId);
|
||||||
|
int volume() const;
|
||||||
|
|
||||||
|
// actions
|
||||||
|
void showNotification(const QString &message, const int &displayTime, const QString ¬ificationType, const ActionId &actionId);
|
||||||
|
void pressButton(const QString &button, const ActionId &actionId);
|
||||||
|
void systemCommand(const QString &command, const ActionId &actionId);
|
||||||
|
void videoLibrary(const QString &command, const ActionId &actionId);
|
||||||
|
void audioLibrary(const QString &command, const ActionId &actionId);
|
||||||
|
|
||||||
|
void update();
|
||||||
|
void checkVersion();
|
||||||
|
|
||||||
|
void connectKodi();
|
||||||
|
void disconnectKodi();
|
||||||
|
|
||||||
|
private:
|
||||||
|
DenonConnection *m_connection;
|
||||||
|
bool m_muted;
|
||||||
|
int m_volume;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void connectionStatusChanged();
|
||||||
|
void stateChanged();
|
||||||
|
void actionExecuted(const ActionId &actionId, const bool &success);
|
||||||
|
void updateDataReceived(const QVariantMap &data);
|
||||||
|
void versionDataReceived(const QVariantMap &data);
|
||||||
|
|
||||||
|
void onPlayerPlay();
|
||||||
|
void onPlayerPause();
|
||||||
|
void onPlayerStop();
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void onVolumeChanged(const int &volume, const bool &muted);
|
||||||
|
void onUpdateFinished(const QVariantMap &data);
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // DENON_H
|
||||||
11
plugins/deviceplugins/denon/denon.pro
Normal file
11
plugins/deviceplugins/denon/denon.pro
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
include(../../plugins.pri)
|
||||||
|
|
||||||
|
TARGET = $$qtLibraryTarget(guh_deviceplugindenon)
|
||||||
|
|
||||||
|
SOURCES += \
|
||||||
|
deviceplugindenon.cpp \
|
||||||
|
denonconnection.cpp
|
||||||
|
|
||||||
|
HEADERS += \
|
||||||
|
deviceplugindenon.h \
|
||||||
|
denonconnection.h
|
||||||
120
plugins/deviceplugins/denon/denonconnection.cpp
Normal file
120
plugins/deviceplugins/denon/denonconnection.cpp
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
* *
|
||||||
|
* Copyright (C) 2015 Simon Stuerz <simon.stuerz@guh.guru> *
|
||||||
|
* Copyright (C) 2016 Bernhard Trinnes <bernhard.trinnes@guh.guru *
|
||||||
|
* *
|
||||||
|
* 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 <http://www.gnu.org/licenses/>. *
|
||||||
|
* *
|
||||||
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
|
#include "denonconnection.h"
|
||||||
|
#include "extern-plugininfo.h"
|
||||||
|
|
||||||
|
DenonConnection::DenonConnection(const QHostAddress &hostAddress, const int &port, QObject *parent) :
|
||||||
|
QObject(parent),
|
||||||
|
m_hostAddress(hostAddress),
|
||||||
|
m_port(port),
|
||||||
|
m_connected(false)
|
||||||
|
{
|
||||||
|
m_socket = new QTcpSocket(this);
|
||||||
|
|
||||||
|
connect(m_socket, &QTcpSocket::connected, this, &DenonConnection::onConnected);
|
||||||
|
connect(m_socket, &QTcpSocket::disconnected, this, &DenonConnection::onDisconnected);
|
||||||
|
connect(m_socket, &QTcpSocket::readyRead, this, &DenonConnection::readData);
|
||||||
|
// Note: error signal will be interpreted as function, not as signal in C++11
|
||||||
|
connect(m_socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(onError(QAbstractSocket::SocketError)));
|
||||||
|
}
|
||||||
|
|
||||||
|
DenonConnection::~DenonConnection()
|
||||||
|
{
|
||||||
|
m_socket->close();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DenonConnection::connectDenon()
|
||||||
|
{
|
||||||
|
if (m_socket->state() == QAbstractSocket::ConnectingState) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
m_socket->connectToHost(m_hostAddress, m_port);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DenonConnection::disconnectDenon()
|
||||||
|
{
|
||||||
|
m_socket->close();
|
||||||
|
}
|
||||||
|
|
||||||
|
QHostAddress DenonConnection::hostAddress() const
|
||||||
|
{
|
||||||
|
return m_hostAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
int DenonConnection::port() const
|
||||||
|
{
|
||||||
|
return m_port;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DenonConnection::connected()
|
||||||
|
{
|
||||||
|
return m_connected;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DenonConnection::sendData(const QByteArray &message)
|
||||||
|
{
|
||||||
|
m_socket->write(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DenonConnection::onConnected()
|
||||||
|
{
|
||||||
|
qCDebug(dcDenon) << "connected successfully to" << hostAddress().toString() << port();
|
||||||
|
setConnected(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DenonConnection::onDisconnected()
|
||||||
|
{
|
||||||
|
qCDebug(dcDenon) << "disconnected from" << hostAddress().toString() << port();
|
||||||
|
setConnected(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DenonConnection::onError(QAbstractSocket::SocketError socketError)
|
||||||
|
{
|
||||||
|
qCWarning(dcDenon) << "socket error:" << socketError << m_socket->errorString();
|
||||||
|
emit socketErrorOccured(socketError);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DenonConnection::readData()
|
||||||
|
{
|
||||||
|
QByteArray data = m_socket->readAll();
|
||||||
|
|
||||||
|
QStringList commandList = QString(data).split("}{");
|
||||||
|
for(int i = 0; i < commandList.count(); ++i) {
|
||||||
|
QString command = commandList.at(i);
|
||||||
|
if(command.isEmpty()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if(i < commandList.count() - 1) {
|
||||||
|
command.append("}");
|
||||||
|
}
|
||||||
|
if(i > 0) {
|
||||||
|
command.prepend("{");
|
||||||
|
}
|
||||||
|
emit dataReady(command.toUtf8());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DenonConnection::setConnected(const bool &connected)
|
||||||
|
{
|
||||||
|
m_connected = connected;
|
||||||
|
emit connectionStatusChanged();
|
||||||
|
}
|
||||||
68
plugins/deviceplugins/denon/denonconnection.h
Normal file
68
plugins/deviceplugins/denon/denonconnection.h
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
* *
|
||||||
|
* Copyright (C) 2015 Simon Stuerz <simon.stuerz@guh.guru> *
|
||||||
|
* Copyright (C) 2016 Bernhard Trinnes <bernhard.trinnes@guh.guru> *
|
||||||
|
* *
|
||||||
|
* 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 <http://www.gnu.org/licenses/>. *
|
||||||
|
* *
|
||||||
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
|
#ifndef DENONCONNECTION_H
|
||||||
|
#define DENONCONNECTION_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QTcpSocket>
|
||||||
|
#include <QHostAddress>
|
||||||
|
|
||||||
|
class DenonConnection : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit DenonConnection(const QHostAddress &hostAddress, const int &port = 23, QObject *parent = 0);
|
||||||
|
~DenonConnection();
|
||||||
|
|
||||||
|
void connectDenon();
|
||||||
|
void disconnectDenon();
|
||||||
|
|
||||||
|
QHostAddress hostAddress() const;
|
||||||
|
int port() const;
|
||||||
|
|
||||||
|
bool connected();
|
||||||
|
|
||||||
|
void sendData(const QByteArray &message);
|
||||||
|
|
||||||
|
private:
|
||||||
|
QTcpSocket *m_socket;
|
||||||
|
|
||||||
|
QHostAddress m_hostAddress;
|
||||||
|
int m_port;
|
||||||
|
bool m_connected;
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void onConnected();
|
||||||
|
void onDisconnected();
|
||||||
|
void onError(QAbstractSocket::SocketError socketError);
|
||||||
|
void readData();
|
||||||
|
|
||||||
|
void setConnected(const bool &connected);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void socketErrorOccured(QAbstractSocket::SocketError socketError);
|
||||||
|
void connectionStatusChanged();
|
||||||
|
void dataReady(const QByteArray &data);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // DENONCONNECTION_H
|
||||||
268
plugins/deviceplugins/denon/deviceplugindenon.cpp
Normal file
268
plugins/deviceplugins/denon/deviceplugindenon.cpp
Normal file
@ -0,0 +1,268 @@
|
|||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
* *
|
||||||
|
* Copyright (C) 2015 Simon Stuerz <simon.stuerz@guh.guru> *
|
||||||
|
* Copyright (C) 2016 Bernhard Trinnes <bernhard.trinnes@guh.guru> *
|
||||||
|
* *
|
||||||
|
* 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 <http://www.gnu.org/licenses/>. *
|
||||||
|
* *
|
||||||
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\page denon.html
|
||||||
|
\title Denon
|
||||||
|
\brief Plugin for Denon AV
|
||||||
|
|
||||||
|
\ingroup plugins
|
||||||
|
\ingroup guh-plugins
|
||||||
|
|
||||||
|
This plug-in supports the
|
||||||
|
\l {http://www.denon.de/de/product/hometheater/avreceivers/avrx1000}{Denon AV Amplifier AVR-X1000}
|
||||||
|
|
||||||
|
\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/denon/deviceplugindenon.json
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#include "deviceplugindenon.h"
|
||||||
|
#include "plugininfo.h"
|
||||||
|
|
||||||
|
DevicePluginDenon::DevicePluginDenon()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
DeviceManager::HardwareResources DevicePluginDenon::requiredHardware() const
|
||||||
|
{
|
||||||
|
return DeviceManager::HardwareResourceTimer;
|
||||||
|
}
|
||||||
|
|
||||||
|
DeviceManager::DeviceSetupStatus DevicePluginDenon::setupDevice(Device *device)
|
||||||
|
{
|
||||||
|
qCDebug(dcDenon) << "Setup Denon device" << device->paramValue("ip").toString();
|
||||||
|
|
||||||
|
// Check if we already have a denon device
|
||||||
|
if (!myDevices().isEmpty()) {
|
||||||
|
qCWarning(dcDenon()) << "Could not add denon device. Only one denon device allowed.";
|
||||||
|
return DeviceManager::DeviceSetupStatusFailure;
|
||||||
|
}
|
||||||
|
|
||||||
|
QHostAddress address(device->paramValue("ip").toString());
|
||||||
|
if (address.isNull()) {
|
||||||
|
qCWarning(dcDenon()) << "Could not parse ip address" << device->paramValue("ip").toString();
|
||||||
|
return DeviceManager::DeviceSetupStatusFailure;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_device = device;
|
||||||
|
m_denonConnection = new DenonConnection(address, 23, this);
|
||||||
|
connect(m_denonConnection.data(), &DenonConnection::connectionStatusChanged, this, &DevicePluginDenon::onConnectionChanged);
|
||||||
|
connect(m_denonConnection.data(), &DenonConnection::socketErrorOccured, this, &DevicePluginDenon::onSocketError);
|
||||||
|
connect(m_denonConnection.data(), &DenonConnection::dataReady, this, &DevicePluginDenon::onDataReceived);
|
||||||
|
|
||||||
|
m_asyncSetups.append(m_denonConnection);
|
||||||
|
m_denonConnection->connectDenon();
|
||||||
|
|
||||||
|
return DeviceManager::DeviceSetupStatusAsync;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DevicePluginDenon::deviceRemoved(Device *device)
|
||||||
|
{
|
||||||
|
qCDebug(dcDenon) << "Delete " << device->name();
|
||||||
|
if (m_denonConnection.isNull()){
|
||||||
|
qCWarning(dcDenon) << "Invalid connection pointer" << device->id().toString();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
m_denonConnection->deleteLater();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DevicePluginDenon::guhTimer()
|
||||||
|
{
|
||||||
|
if (m_denonConnection.isNull())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!m_denonConnection->connected()) {
|
||||||
|
m_denonConnection->connectDenon();
|
||||||
|
} else {
|
||||||
|
m_denonConnection->sendData("PW?\rSI?\rMV?\r");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DeviceManager::DeviceError DevicePluginDenon::executeAction(Device *device, const Action &action)
|
||||||
|
{
|
||||||
|
qCDebug(dcDenon) << "Execute action" << device->id() << action.id() << action.params();
|
||||||
|
if (device->deviceClassId() == AVRX1000DeviceClassId) {
|
||||||
|
|
||||||
|
// check connection state
|
||||||
|
if (m_denonConnection.isNull() || !m_denonConnection->connected())
|
||||||
|
return DeviceManager::DeviceErrorHardwareNotAvailable;
|
||||||
|
|
||||||
|
// check if the requested action is our "update" action ...
|
||||||
|
if (action.actionTypeId() == powerActionTypeId) {
|
||||||
|
|
||||||
|
// Print information that we are executing now the update action
|
||||||
|
qCDebug(dcDenon) << "set power action" << action.id();
|
||||||
|
qCDebug(dcDenon) << "power: " << action.param("power").value().Bool;
|
||||||
|
|
||||||
|
if (action.param("power").value().toBool() == true){
|
||||||
|
QByteArray cmd = "PWON\r";
|
||||||
|
qCDebug(dcDenon) << "Execute power: " << action.id() << cmd;
|
||||||
|
m_denonConnection->sendData(cmd);
|
||||||
|
} else {
|
||||||
|
QByteArray cmd = "PWSTANDBY\r";
|
||||||
|
qCDebug(dcDenon) << "Execute power: " << action.id() << cmd;
|
||||||
|
m_denonConnection->sendData(cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
return DeviceManager::DeviceErrorNoError;
|
||||||
|
|
||||||
|
} else if (action.actionTypeId() == volumeActionTypeId) {
|
||||||
|
|
||||||
|
QByteArray vol = action.param("volume").value().toByteArray();
|
||||||
|
QByteArray cmd = "MV" + vol + "\r";
|
||||||
|
|
||||||
|
qCDebug(dcDenon) << "Execute volume" << action.id() << cmd;
|
||||||
|
m_denonConnection->sendData(cmd);
|
||||||
|
|
||||||
|
return DeviceManager::DeviceErrorNoError;
|
||||||
|
|
||||||
|
} else if (action.actionTypeId() == channelActionTypeId) {
|
||||||
|
|
||||||
|
qCDebug(dcDenon) << "Execute update action" << action.id();
|
||||||
|
QByteArray channel = action.param("channel").value().toByteArray();
|
||||||
|
QByteArray cmd = "SI" + channel + "\r";
|
||||||
|
|
||||||
|
qCDebug(dcDenon) << "Change to channel:" << cmd;
|
||||||
|
m_denonConnection->sendData(cmd);
|
||||||
|
|
||||||
|
return DeviceManager::DeviceErrorNoError;
|
||||||
|
}
|
||||||
|
return DeviceManager::DeviceErrorActionTypeNotFound;
|
||||||
|
}
|
||||||
|
return DeviceManager::DeviceErrorDeviceClassNotFound;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DevicePluginDenon::onConnectionChanged()
|
||||||
|
{
|
||||||
|
// if the device is connected
|
||||||
|
if (m_denonConnection->connected()) {
|
||||||
|
// and from the first setup
|
||||||
|
if (m_asyncSetups.contains(m_denonConnection)) {
|
||||||
|
m_asyncSetups.removeAll(m_denonConnection);
|
||||||
|
m_denonConnection->sendData("PW?\rSI?\rMV?\r");
|
||||||
|
emit deviceSetupFinished(m_device, DeviceManager::DeviceSetupStatusSuccess);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set connection status
|
||||||
|
m_device->setStateValue(connectedStateTypeId, m_denonConnection->connected());
|
||||||
|
}
|
||||||
|
|
||||||
|
void DevicePluginDenon::onDataReceived(const QByteArray &data)
|
||||||
|
{
|
||||||
|
qDebug(dcDenon) << "Data received" << data;
|
||||||
|
|
||||||
|
// if there is no device, return
|
||||||
|
if (m_device.isNull())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (data.contains("MV") && !data.contains("MAX")){
|
||||||
|
int index = data.indexOf("MV");
|
||||||
|
int vol = data.mid(index+2, 2).toInt();
|
||||||
|
|
||||||
|
qDebug(dcDenon) << "Update volume:" << vol;
|
||||||
|
m_device->setStateValue(volumeStateTypeId, vol);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data.contains("SI")) {
|
||||||
|
QString cmd = NULL;
|
||||||
|
if (data.contains("TUNER")) {
|
||||||
|
cmd = "TUNER";
|
||||||
|
} else if (data.contains("DVD")) {
|
||||||
|
cmd = "DVD";
|
||||||
|
} else if (data.contains("BD")) {
|
||||||
|
cmd = "BD";
|
||||||
|
} else if (data.contains("TV")) {
|
||||||
|
cmd = "TV";
|
||||||
|
} else if (data.contains("SAT/CBL")) {
|
||||||
|
cmd = "SAT/CBL";
|
||||||
|
} else if (data.contains("MPLAY")) {
|
||||||
|
cmd = "MPLAY";
|
||||||
|
} else if (data.contains("GAME")) {
|
||||||
|
cmd = "GAME";
|
||||||
|
} else if (data.contains("AUX1")) {
|
||||||
|
cmd = "AUX1";
|
||||||
|
} else if (data.contains("NET")) {
|
||||||
|
cmd = "NET";
|
||||||
|
} else if (data.contains("PANDORA")) {
|
||||||
|
cmd = "PANDORA";
|
||||||
|
} else if (data.contains("SIRIUSXM")) {
|
||||||
|
cmd = "SIRIUSXM";
|
||||||
|
} else if (data.contains("SPOTIFY")) {
|
||||||
|
cmd = "SPOTIFY";
|
||||||
|
} else if (data.contains("FLICKR")) {
|
||||||
|
cmd = "FLICKR";
|
||||||
|
} else if (data.contains("FAVORITES")) {
|
||||||
|
cmd = "FAVORITES";
|
||||||
|
} else if (data.contains("IRADIO")) {
|
||||||
|
cmd = "IRADIO";
|
||||||
|
} else if (data.contains("SERVER")) {
|
||||||
|
cmd = "SERVER";
|
||||||
|
} else if (data.contains("USB/IPOD")) {
|
||||||
|
cmd = "USB/IPOD";
|
||||||
|
} else if (data.contains("IPD")) {
|
||||||
|
cmd = "IPD";
|
||||||
|
} else if (data.contains("IRP")) {
|
||||||
|
cmd = "IRP";
|
||||||
|
} else if (data.contains("FVP")) {
|
||||||
|
cmd = "FVP";
|
||||||
|
}
|
||||||
|
|
||||||
|
qDebug(dcDenon) << "Update channel:" << cmd;
|
||||||
|
m_device->setStateValue(channelStateTypeId, cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data.contains("PWON")) {
|
||||||
|
qDebug(dcDenon) << "Update power on";
|
||||||
|
m_device->setStateValue(powerStateTypeId, true);
|
||||||
|
} else if (data.contains("PWSTANDBY")) {
|
||||||
|
qDebug(dcDenon) << "Update power off";
|
||||||
|
m_device->setStateValue(powerStateTypeId, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DevicePluginDenon::onSocketError()
|
||||||
|
{
|
||||||
|
// if there is no device, return
|
||||||
|
if (m_device.isNull())
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Check if setup running for this device
|
||||||
|
if (m_asyncSetups.contains(m_denonConnection)) {
|
||||||
|
qCWarning(dcDenon()) << "Could not add device. The setup failed.";
|
||||||
|
emit deviceSetupFinished(m_device, DeviceManager::DeviceSetupStatusFailure);
|
||||||
|
// Delete the connection, the device will not be added and
|
||||||
|
// the connection will be created in the next setup
|
||||||
|
m_denonConnection->deleteLater();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
68
plugins/deviceplugins/denon/deviceplugindenon.h
Normal file
68
plugins/deviceplugins/denon/deviceplugindenon.h
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
* *
|
||||||
|
* Copyright (C) 2015 Simon Stuerz <simon.stuerz@guh.guru> *
|
||||||
|
* Copyright (C) 2016 Bernhard Trinnes <bernhard.trinnes@guh.guru> *
|
||||||
|
* *
|
||||||
|
* 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 <http://www.gnu.org/licenses/>. *
|
||||||
|
* *
|
||||||
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
|
#ifndef DEVICEPLUGINDENON_H
|
||||||
|
#define DEVICEPLUGINDENON_H
|
||||||
|
|
||||||
|
#include "devicemanager.h"
|
||||||
|
#include "plugin/deviceplugin.h"
|
||||||
|
|
||||||
|
|
||||||
|
#include <QHash>
|
||||||
|
#include <QObject>
|
||||||
|
#include <QPointer>
|
||||||
|
#include <QHostAddress>
|
||||||
|
#include <QNetworkReply>
|
||||||
|
|
||||||
|
#include "denonconnection.h"
|
||||||
|
|
||||||
|
class DevicePluginDenon : public DevicePlugin
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
Q_PLUGIN_METADATA(IID "guru.guh.DevicePlugin" FILE "deviceplugindenon.json")
|
||||||
|
Q_INTERFACES(DevicePlugin)
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit DevicePluginDenon();
|
||||||
|
|
||||||
|
DeviceManager::HardwareResources requiredHardware() const override;
|
||||||
|
DeviceManager::DeviceSetupStatus setupDevice(Device *device) override;
|
||||||
|
void deviceRemoved(Device *device) override;
|
||||||
|
|
||||||
|
DeviceManager::DeviceError executeAction(Device *device, const Action &action) override;
|
||||||
|
void guhTimer() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
QPointer<Device> m_device;
|
||||||
|
QPointer<DenonConnection> m_denonConnection;
|
||||||
|
QList<DenonConnection *> m_asyncSetups;
|
||||||
|
|
||||||
|
QHash <ActionId, Device *> m_asyncActions;
|
||||||
|
QHash <QNetworkReply *, ActionId> m_asyncActionReplies;
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void onConnectionChanged();
|
||||||
|
void onDataReceived(const QByteArray &data);
|
||||||
|
void onSocketError();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // DEVICEPLUGINDENON_H
|
||||||
88
plugins/deviceplugins/denon/deviceplugindenon.json
Normal file
88
plugins/deviceplugins/denon/deviceplugindenon.json
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
{
|
||||||
|
"name": "Denon",
|
||||||
|
"idName": "Denon",
|
||||||
|
"id": "cd758269-dbbb-4ef0-80ab-48bd9a8a2765",
|
||||||
|
"vendors": [
|
||||||
|
{
|
||||||
|
"id": "cf0a9644-2c13-4daf-85c1-ad88d6745b42",
|
||||||
|
"name": "Denon",
|
||||||
|
"idName": "denon",
|
||||||
|
"deviceClasses": [
|
||||||
|
{
|
||||||
|
"deviceClassId": "1cd3d67e-aba0-450e-9e2a-483a1527aba6",
|
||||||
|
"idName": "AVRX1000",
|
||||||
|
"name": "AVR X1000",
|
||||||
|
"createMethods": ["user"],
|
||||||
|
"deviceIcon": "Hifi",
|
||||||
|
"basicTags": [
|
||||||
|
"Device",
|
||||||
|
"Multimedia"
|
||||||
|
],
|
||||||
|
"paramTypes": [
|
||||||
|
{
|
||||||
|
"name": "ip",
|
||||||
|
"type" : "QString",
|
||||||
|
"inputType": "IPv4Address"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"stateTypes": [
|
||||||
|
{
|
||||||
|
"id": "4d1790bf-28c6-4c1f-8892-ba1a0ef140f5",
|
||||||
|
"idName": "connected",
|
||||||
|
"name": "connected",
|
||||||
|
"type": "bool"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "power",
|
||||||
|
"id": "1cdb6b54-6831-4900-95b2-c78f64497701",
|
||||||
|
"idName": "power",
|
||||||
|
"type": "bool",
|
||||||
|
"defaultValue": false,
|
||||||
|
"writable": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "volume",
|
||||||
|
"id": "773636b9-304d-463a-8755-fc7488dc0ff3",
|
||||||
|
"idName": "volume",
|
||||||
|
"type": "int",
|
||||||
|
"unit": "Dezibel",
|
||||||
|
"defaultValue": 0,
|
||||||
|
"minValue": 0,
|
||||||
|
"maxValue": 80,
|
||||||
|
"writable": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "channel",
|
||||||
|
"id": "f29ffa2c-31d6-4d88-b160-a38288c82ce1",
|
||||||
|
"idName": "channel",
|
||||||
|
"type": "QString",
|
||||||
|
"writable": true,
|
||||||
|
"possibleValues": [
|
||||||
|
"TUNER",
|
||||||
|
"DVD",
|
||||||
|
"BD",
|
||||||
|
"TV",
|
||||||
|
"SAT/CBL",
|
||||||
|
"MPLAY",
|
||||||
|
"GAME",
|
||||||
|
"AUX1",
|
||||||
|
"NET",
|
||||||
|
"SPOTIFY",
|
||||||
|
"FLICKR",
|
||||||
|
"FAVORITES",
|
||||||
|
"IRADIO",
|
||||||
|
"SERVER",
|
||||||
|
"USB/IPOD",
|
||||||
|
"USB",
|
||||||
|
"IPD",
|
||||||
|
"IRP",
|
||||||
|
"FVP"
|
||||||
|
],
|
||||||
|
"defaultValue": "TUNER"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@ -25,3 +25,4 @@ SUBDIRS += elro \
|
|||||||
osdomotics \
|
osdomotics \
|
||||||
ws2812 \
|
ws2812 \
|
||||||
orderbutton \
|
orderbutton \
|
||||||
|
denon \
|
||||||
|
|||||||
Reference in New Issue
Block a user