added kodi connection and jsonhandler
This commit is contained in:
parent
ceaad7c7fd
commit
1f35f78238
2
debian/guh-plugins.install
vendored
2
debian/guh-plugins.install
vendored
@ -17,3 +17,5 @@ usr/lib/guh/plugins/libguh_devicepluginunitec.so
|
||||
usr/lib/guh/plugins/libguh_devicepluginleynew.so
|
||||
usr/lib/guh/plugins/libguh_deviceplugintune.so
|
||||
usr/lib/guh/plugins/libguh_devicepluginudpcommander.so
|
||||
usr/lib/guh/plugins/libguh_devicepluginkodi.so
|
||||
|
||||
|
||||
@ -48,3 +48,4 @@ Q_LOGGING_CATEGORY(dcUdpCommander, "UdpCommander")
|
||||
Q_LOGGING_CATEGORY(dcWakeOnLan, "WakeOnLan")
|
||||
Q_LOGGING_CATEGORY(dcWemo, "Wemo")
|
||||
Q_LOGGING_CATEGORY(dcWifiDetector, "WifiDetector")
|
||||
Q_LOGGING_CATEGORY(dcKodi, "Kodi")
|
||||
|
||||
@ -53,6 +53,7 @@ Q_DECLARE_LOGGING_CATEGORY(dcUdpCommander)
|
||||
Q_DECLARE_LOGGING_CATEGORY(dcWakeOnLan)
|
||||
Q_DECLARE_LOGGING_CATEGORY(dcWemo)
|
||||
Q_DECLARE_LOGGING_CATEGORY(dcWifiDetector)
|
||||
Q_DECLARE_LOGGING_CATEGORY(dcKodi)
|
||||
|
||||
|
||||
|
||||
|
||||
@ -25,6 +25,8 @@
|
||||
\ingroup plugins
|
||||
\ingroup network
|
||||
|
||||
TODO: description
|
||||
|
||||
|
||||
\chapter Plugin properties
|
||||
Following JSON file contains the definition and the description of all available \l{DeviceClass}{DeviceClasses}
|
||||
@ -45,6 +47,7 @@
|
||||
#include "devicepluginkodi.h"
|
||||
#include "plugin/device.h"
|
||||
#include "plugininfo.h"
|
||||
#include "loggingcategories.h"
|
||||
|
||||
DevicePluginKodi::DevicePluginKodi()
|
||||
{
|
||||
@ -53,52 +56,85 @@ DevicePluginKodi::DevicePluginKodi()
|
||||
|
||||
DeviceManager::HardwareResources DevicePluginKodi::requiredHardware() const
|
||||
{
|
||||
return DeviceManager::HardwareResourceNone;
|
||||
return DeviceManager::HardwareResourceTimer | DeviceManager::HardwareResourceUpnpDisovery;
|
||||
}
|
||||
|
||||
DeviceManager::DeviceSetupStatus DevicePluginKodi::setupDevice(Device *device)
|
||||
{
|
||||
Q_UNUSED(device)
|
||||
KodiConnection *kodiConnection = new KodiConnection(QHostAddress(device->paramValue("ip").toString()), 9090, this);
|
||||
|
||||
connect(kodiConnection, &KodiConnection::connectionStateChanged, this, &DevicePluginKodi::onConnectionChanged);
|
||||
|
||||
kodiConnection->connectToKodi();
|
||||
|
||||
m_kodiConnections.insert(kodiConnection, device);
|
||||
return DeviceManager::DeviceSetupStatusSuccess;
|
||||
}
|
||||
|
||||
void DevicePluginKodi::deviceRemoved(Device *device)
|
||||
{
|
||||
Q_UNUSED(device)
|
||||
KodiConnection *kodiConnection = m_kodiConnections.key(device);
|
||||
m_kodiConnections.remove(kodiConnection);
|
||||
qCDebug(dcKodi) << "delete Kodi" << device->paramValue("name");
|
||||
kodiConnection->deleteLater();
|
||||
}
|
||||
|
||||
DeviceManager::DeviceSetupStatus DevicePluginKodi::confirmPairing(const PairingTransactionId &pairingTransactionId, const DeviceClassId &deviceClassId, const ParamList ¶ms)
|
||||
{
|
||||
Q_UNUSED(pairingTransactionId)
|
||||
Q_UNUSED(deviceClassId)
|
||||
Q_UNUSED(params)
|
||||
|
||||
return DeviceManager::DeviceSetupStatusSuccess;
|
||||
}
|
||||
|
||||
DeviceManager::DeviceError DevicePluginKodi::discoverDevices(const DeviceClassId &deviceClassId, const ParamList ¶ms)
|
||||
{
|
||||
Q_UNUSED(params)
|
||||
Q_UNUSED(deviceClassId)
|
||||
|
||||
qCDebug(dcKodi) << "start Kodi UPnP search";
|
||||
upnpDiscover();
|
||||
|
||||
return DeviceManager::DeviceErrorNoError;
|
||||
return DeviceManager::DeviceErrorAsync;
|
||||
}
|
||||
|
||||
void DevicePluginKodi::upnpDiscoveryFinished(const QList<UpnpDeviceDescriptor> &upnpDeviceDescriptorList)
|
||||
{
|
||||
Q_UNUSED(upnpDeviceDescriptorList)
|
||||
|
||||
QList<DeviceDescriptor> deviceDescriptors;
|
||||
foreach (const UpnpDeviceDescriptor &upnpDescriptor, upnpDeviceDescriptorList) {
|
||||
if (upnpDescriptor.modelName().contains("Kodi")) {
|
||||
qCDebug(dcKodi) << upnpDescriptor;
|
||||
DeviceDescriptor deviceDescriptor(kodiDeviceClassId, "Kodi - Media Center", upnpDescriptor.hostAddress().toString());
|
||||
ParamList params;
|
||||
params.append(Param("name", upnpDescriptor.friendlyName()));
|
||||
params.append(Param("ip", upnpDescriptor.hostAddress().toString()));
|
||||
params.append(Param("port", 9090));
|
||||
deviceDescriptor.setParams(params);
|
||||
deviceDescriptors.append(deviceDescriptor);
|
||||
}
|
||||
}
|
||||
emit devicesDiscovered(kodiDeviceClassId, deviceDescriptors);
|
||||
}
|
||||
|
||||
void DevicePluginKodi::networkManagerReplyReady(QNetworkReply *reply)
|
||||
DeviceManager::DeviceError DevicePluginKodi::executeAction(Device *device, const Action &action)
|
||||
{
|
||||
Q_UNUSED(reply)
|
||||
if (device->deviceClassId() == kodiDeviceClassId) {
|
||||
if (action.actionTypeId() == sendNotificationActionTypeId) {
|
||||
|
||||
|
||||
return DeviceManager::DeviceErrorNoError;
|
||||
} else if (action.actionTypeId() == volumeActionTypeId) {
|
||||
|
||||
|
||||
return DeviceManager::DeviceErrorNoError;
|
||||
}
|
||||
return DeviceManager::DeviceErrorActionTypeNotFound;
|
||||
}
|
||||
return DeviceManager::DeviceErrorDeviceClassNotFound;
|
||||
}
|
||||
|
||||
void DevicePluginKodi::guhTimer()
|
||||
void DevicePluginKodi::onConnectionChanged(const bool &connected)
|
||||
{
|
||||
KodiConnection *kodiConnection = static_cast<KodiConnection *>(sender());
|
||||
Device *device = m_kodiConnections.value(kodiConnection);
|
||||
|
||||
device->setStateValue(connectedStateTypeId, connected);
|
||||
}
|
||||
|
||||
void DevicePluginKodi::dataReceived(const QByteArray &data)
|
||||
{
|
||||
KodiConnection *kodiConnection = static_cast<KodiConnection *>(sender());
|
||||
emit dataReady(kodiConnection, data);
|
||||
}
|
||||
|
||||
|
||||
@ -22,9 +22,11 @@
|
||||
#define DEVICEPLUGINKODI_H
|
||||
|
||||
#include "plugin/deviceplugin.h"
|
||||
#include "kodiconnection.h"
|
||||
|
||||
#include <QHash>
|
||||
#include <QDebug>
|
||||
#include <QTcpSocket>
|
||||
|
||||
class DevicePluginKodi : public DevicePlugin
|
||||
{
|
||||
@ -39,16 +41,20 @@ public:
|
||||
DeviceManager::DeviceSetupStatus setupDevice(Device *device) override;
|
||||
void deviceRemoved(Device *device) override;
|
||||
|
||||
DeviceManager::DeviceSetupStatus confirmPairing(const PairingTransactionId &pairingTransactionId, const DeviceClassId &deviceClassId, const ParamList ¶ms) override;
|
||||
|
||||
DeviceManager::DeviceError discoverDevices(const DeviceClassId &deviceClassId, const ParamList ¶ms) override;
|
||||
void upnpDiscoveryFinished(const QList<UpnpDeviceDescriptor> &upnpDeviceDescriptorList) override;
|
||||
void networkManagerReplyReady(QNetworkReply *reply) override;
|
||||
void guhTimer() override;
|
||||
|
||||
DeviceManager::DeviceError executeAction(Device *device, const Action &action) override;
|
||||
|
||||
private:
|
||||
QHash<KodiConnection *, Device *> m_kodiConnections;
|
||||
|
||||
signals:
|
||||
void dataReady(KodiConnection *kodiConnection, const QByteArray &data);
|
||||
|
||||
private slots:
|
||||
void onConnectionChanged(const bool &connected);
|
||||
void dataReceived(const QByteArray &data);
|
||||
|
||||
};
|
||||
|
||||
|
||||
@ -8,13 +8,60 @@
|
||||
"deviceClasses": [
|
||||
{
|
||||
"deviceClassId": "d09953e3-c5bd-415b-973b-0d0bf2be3f69",
|
||||
"idName": "kodi",
|
||||
"name": "Kodi",
|
||||
"createMethods": ["discovery"],
|
||||
"createMethods": ["user", "discovery"],
|
||||
"paramTypes": [
|
||||
{
|
||||
"name": "name",
|
||||
"type": "QString",
|
||||
"inputType": "TextLine"
|
||||
},
|
||||
{
|
||||
"name": "ip",
|
||||
"type" : "QString",
|
||||
"inputType": "IPv4Address"
|
||||
},
|
||||
{
|
||||
"name": "port",
|
||||
"type" : "int"
|
||||
}
|
||||
],
|
||||
"stateTypes": [
|
||||
{
|
||||
"id": "09dfbd40-c97c-4a20-9ecd-f80e389a4864",
|
||||
"idName": "connected",
|
||||
"name": "connected",
|
||||
"type": "bool"
|
||||
},
|
||||
{
|
||||
"id": "bc98cdb0-4d0e-48ca-afc7-922e49bb7813",
|
||||
"idName": "mute",
|
||||
"name": "mute",
|
||||
"type": "bool"
|
||||
},
|
||||
{
|
||||
"id": "9dfe5d78-4c3f-497c-bab1-bb9fdf7e93a9",
|
||||
"idName": "volume",
|
||||
"name": "volume",
|
||||
"unit": "Percentage",
|
||||
"type": "int",
|
||||
"writable": true,
|
||||
"minValue": 0,
|
||||
"maxValue": 100
|
||||
}
|
||||
],
|
||||
"actionTypes": [
|
||||
{
|
||||
"id": "dc0aa3b5-4eae-4e58-a4ac-d4c124da53f1",
|
||||
"idName": "sendNotification",
|
||||
"name": "send notification",
|
||||
"paramTypes": [
|
||||
{
|
||||
"name": "message",
|
||||
"type": "QString"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
6
plugins/deviceplugins/kodi/jsonhandler.cpp
Normal file
6
plugins/deviceplugins/kodi/jsonhandler.cpp
Normal file
@ -0,0 +1,6 @@
|
||||
#include "jsonhandler.h"
|
||||
|
||||
JsonHandler::JsonHandler(QObject *parent) :
|
||||
QObject(parent)
|
||||
{
|
||||
}
|
||||
18
plugins/deviceplugins/kodi/jsonhandler.h
Normal file
18
plugins/deviceplugins/kodi/jsonhandler.h
Normal file
@ -0,0 +1,18 @@
|
||||
#ifndef JSONHANDLER_H
|
||||
#define JSONHANDLER_H
|
||||
|
||||
#include <QObject>
|
||||
|
||||
class JsonHandler : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit JsonHandler(QObject *parent = 0);
|
||||
|
||||
signals:
|
||||
|
||||
public slots:
|
||||
|
||||
};
|
||||
|
||||
#endif // JSONHANDLER_H
|
||||
@ -3,8 +3,12 @@ include(../../plugins.pri)
|
||||
TARGET = $$qtLibraryTarget(guh_devicepluginkodi)
|
||||
|
||||
SOURCES += \
|
||||
devicepluginkodi.cpp
|
||||
devicepluginkodi.cpp \
|
||||
kodiconnection.cpp \
|
||||
jsonhandler.cpp
|
||||
|
||||
HEADERS += \
|
||||
devicepluginkodi.h
|
||||
devicepluginkodi.h \
|
||||
kodiconnection.h \
|
||||
jsonhandler.h
|
||||
|
||||
|
||||
85
plugins/deviceplugins/kodi/kodiconnection.cpp
Normal file
85
plugins/deviceplugins/kodi/kodiconnection.cpp
Normal file
@ -0,0 +1,85 @@
|
||||
#include "kodiconnection.h"
|
||||
#include "loggingcategories.h"
|
||||
|
||||
KodiConnection::KodiConnection(const QHostAddress &hostAddress, const int &port, QObject *parent) :
|
||||
QObject(parent),
|
||||
m_hostAddress(hostAddress),
|
||||
m_port(port)
|
||||
{
|
||||
m_socket = new QTcpSocket(this);
|
||||
|
||||
connect(m_socket, &QTcpSocket::connected, this, &KodiConnection::onConnected);
|
||||
connect(m_socket, &QTcpSocket::disconnected, this, &KodiConnection::onDisconnected);
|
||||
connect(m_socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(onError(QAbstractSocket::SocketError)));
|
||||
connect(m_socket, &QTcpSocket::readyRead, this, &KodiConnection::readData);
|
||||
}
|
||||
|
||||
void KodiConnection::connectToKodi()
|
||||
{
|
||||
m_socket->connectToHost(m_hostAddress, m_port);
|
||||
}
|
||||
|
||||
void KodiConnection::disconnectFromKodi()
|
||||
{
|
||||
m_socket->close();
|
||||
}
|
||||
|
||||
QHostAddress KodiConnection::hostAddress() const
|
||||
{
|
||||
return m_hostAddress;
|
||||
}
|
||||
|
||||
int KodiConnection::port() const
|
||||
{
|
||||
return m_port;
|
||||
}
|
||||
|
||||
void KodiConnection::onConnected()
|
||||
{
|
||||
qCDebug(dcKodi) << "connected successfully to" << hostAddress().toString() << port();
|
||||
emit connectionStateChanged(true);
|
||||
}
|
||||
|
||||
void KodiConnection::onDisconnected()
|
||||
{
|
||||
qCDebug(dcKodi) << "disconnected from" << hostAddress().toString() << port();
|
||||
emit connectionStateChanged(false);
|
||||
}
|
||||
|
||||
void KodiConnection::onError(QAbstractSocket::SocketError socketError)
|
||||
{
|
||||
qCWarning(dcKodi) << "socket error:" << socketError << m_socket->errorString();
|
||||
}
|
||||
|
||||
void KodiConnection::readData()
|
||||
{
|
||||
QByteArray data = m_socket->readAll();
|
||||
|
||||
QJsonParseError error;
|
||||
QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &error);
|
||||
|
||||
if(error.error != QJsonParseError::NoError) {
|
||||
qCWarning(dcKodi) << "failed to parse JSON data:" << data << ":" << error.errorString();
|
||||
return;
|
||||
}
|
||||
qCDebug(dcKodi) << "data received:" << jsonDoc.toJson();
|
||||
|
||||
unsigned short m_IconSize;
|
||||
emit dataReady(data);
|
||||
}
|
||||
|
||||
void KodiConnection::sendData(const QString &method, const QVariantMap ¶ms)
|
||||
{
|
||||
QVariantMap package;
|
||||
package.insert("id", m_id);
|
||||
package.insert("method", method);
|
||||
package.insert("params", params);
|
||||
package.insert("jsonrpc", "2.0");
|
||||
m_id++;
|
||||
|
||||
QJsonDocument jsonDoc = QJsonDocument::fromVariant(package);
|
||||
qCDebug(dcKodi) << "sending data" << jsonDoc.toJson();
|
||||
|
||||
m_socket->write(jsonDoc.toJson());
|
||||
}
|
||||
|
||||
45
plugins/deviceplugins/kodi/kodiconnection.h
Normal file
45
plugins/deviceplugins/kodi/kodiconnection.h
Normal file
@ -0,0 +1,45 @@
|
||||
#ifndef KODICONNECTION_H
|
||||
#define KODICONNECTION_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QTcpSocket>
|
||||
#include <QHostAddress>
|
||||
#include <QJsonDocument>
|
||||
|
||||
class KodiConnection : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit KodiConnection(const QHostAddress &hostAddress, const int &port = 9090, QObject *parent = 0);
|
||||
|
||||
void connectToKodi();
|
||||
void disconnectFromKodi();
|
||||
|
||||
QHostAddress hostAddress() const;
|
||||
int port() const;
|
||||
|
||||
private:
|
||||
QHostAddress m_hostAddress;
|
||||
int m_port;
|
||||
int m_id;
|
||||
|
||||
|
||||
|
||||
QTcpSocket *m_socket;
|
||||
|
||||
private slots:
|
||||
void onConnected();
|
||||
void onDisconnected();
|
||||
void onError(QAbstractSocket::SocketError socketError);
|
||||
void readData();
|
||||
|
||||
signals:
|
||||
void connectionStateChanged(const bool &connected);
|
||||
void dataReady(const QByteArray &data);
|
||||
|
||||
public slots:
|
||||
void sendData(const QString &method, const QVariantMap ¶ms = QVariantMap());
|
||||
|
||||
};
|
||||
|
||||
#endif // KODICONNECTION_H
|
||||
@ -81,6 +81,7 @@ int main(int argc, char *argv[])
|
||||
s_loggingFilters.insert("WakeOnLan", false);
|
||||
s_loggingFilters.insert("Wemo", false);
|
||||
s_loggingFilters.insert("WifiDetector", false);
|
||||
s_loggingFilters.insert("Kodi", true);
|
||||
|
||||
|
||||
QCommandLineParser parser;
|
||||
|
||||
Reference in New Issue
Block a user