From 4dee52a29768e0af77f6a23fe01813667d107c32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20St=C3=BCrz?= Date: Thu, 12 Feb 2015 17:35:25 +0100 Subject: [PATCH] added support for multiple upnp discovery requests --- .../hardware/upnpdiscovery/upnpdiscovery.cpp | 76 +++++++------------ libguh/hardware/upnpdiscovery/upnpdiscovery.h | 17 +++-- .../upnpdiscovery/upnpdiscoveryrequest.cpp | 73 ++++++++++++++++++ .../upnpdiscovery/upnpdiscoveryrequest.h | 43 +++++++++++ libguh/libguh.pro | 5 +- .../lgsmarttv/devicepluginlgsmarttv.cpp | 8 ++ 6 files changed, 162 insertions(+), 60 deletions(-) create mode 100644 libguh/hardware/upnpdiscovery/upnpdiscoveryrequest.cpp create mode 100644 libguh/hardware/upnpdiscovery/upnpdiscoveryrequest.h diff --git a/libguh/hardware/upnpdiscovery/upnpdiscovery.cpp b/libguh/hardware/upnpdiscovery/upnpdiscovery.cpp index bb249358..8f1f0893 100644 --- a/libguh/hardware/upnpdiscovery/upnpdiscovery.cpp +++ b/libguh/hardware/upnpdiscovery/upnpdiscovery.cpp @@ -38,17 +38,9 @@ UpnpDiscovery::UpnpDiscovery(QObject *parent) : return; } - m_deviceList.clear(); - m_informationRequestList.clear(); - // network access manager for requesting device information m_networkAccessManager = new QNetworkAccessManager(this); - connect(m_networkAccessManager,SIGNAL(finished(QNetworkReply*)),this,SLOT(replyFinished(QNetworkReply*))); - - // discovery refresh timer - m_timer = new QTimer(this); - m_timer->setSingleShot(true); - connect(m_timer, &QTimer::timeout, this, &UpnpDiscovery::discoverTimeout); + connect(m_networkAccessManager, &QNetworkAccessManager::finished, this, &UpnpDiscovery::replyFinished); connect(this,SIGNAL(error(QAbstractSocket::SocketError)),this,SLOT(error(QAbstractSocket::SocketError))); connect(this, &UpnpDiscovery::readyRead, this, &UpnpDiscovery::readData); @@ -58,48 +50,32 @@ UpnpDiscovery::UpnpDiscovery(QObject *parent) : bool UpnpDiscovery::discoverDevices(const QString &searchTarget, const QString &userAgent, const PluginId &pluginId) { - // clear the list... - m_deviceList.clear(); - foreach (QNetworkReply* reply, m_informationRequestList.keys()) { - m_informationRequestList.remove(reply); - reply->deleteLater(); - } - if(state() != BoundState){ qDebug() << "ERROR: UPnP not bound to port 1900"; return false; } - m_searchTarget = searchTarget; - m_userAgent = userAgent; - m_pluginId = pluginId; + // create a new request + UpnpDiscoveryRequest *request = new UpnpDiscoveryRequest(this, pluginId, searchTarget, userAgent); + connect(request, &UpnpDiscoveryRequest::discoveryTimeout, this, &UpnpDiscovery::discoverTimeout); - QByteArray ssdpSearchMessage = QByteArray("M-SEARCH * HTTP/1.1\r\n" - "HOST:239.255.255.250:1900\r\n" - "MAN:\"ssdp:discover\"\r\n" - "MX:2\r\n" - "ST: " + m_searchTarget.toUtf8() + "\r\n" - "USR-AGENT: " + m_userAgent.toUtf8() + "\r\n\r\n"); - - qDebug() << "--> UPnP discovery called."; - writeDatagram(ssdpSearchMessage, m_host, m_port); - - m_timer->start(3000); + request->discover(); + m_discoverRequests.append(request); return true; } -void UpnpDiscovery::requestDeviceInformation(const UpnpDeviceDescriptor &upnpDeviceDescriptor) +void UpnpDiscovery::requestDeviceInformation(const QNetworkRequest &networkRequest, const UpnpDeviceDescriptor &upnpDeviceDescriptor) { - QNetworkRequest deviceRequest; - deviceRequest.setUrl(upnpDeviceDescriptor.location()); - deviceRequest.setHeader(QNetworkRequest::ContentTypeHeader,QVariant("text/xml")); - deviceRequest.setHeader(QNetworkRequest::UserAgentHeader,QVariant(m_userAgent)); - QNetworkReply *replay; - replay = m_networkAccessManager->get(deviceRequest); + replay = m_networkAccessManager->get(networkRequest); m_informationRequestList.insert(replay, upnpDeviceDescriptor); } +void UpnpDiscovery::sendToMulticast(const QByteArray &data) +{ + writeDatagram(data, m_host, m_port); +} + void UpnpDiscovery::error(QAbstractSocket::SocketError error) { qWarning() << errorString() << error; @@ -117,8 +93,8 @@ void UpnpDiscovery::readData() readDatagram(data.data(), data.size(), &hostAddress); } -// qDebug() << "======================"; -// qDebug() << data; + qDebug() << "======================"; + qDebug() << data; if (data.contains("NOTIFY")) { emit upnpNotify(data); @@ -144,7 +120,10 @@ void UpnpDiscovery::readData() upnpDeviceDescriptor.setHostAddress(hostAddress); upnpDeviceDescriptor.setPort(location.port()); - requestDeviceInformation(upnpDeviceDescriptor); + foreach (UpnpDiscoveryRequest *upnpDiscoveryRequest, m_discoverRequests) { + QNetworkRequest networkRequest = upnpDiscoveryRequest->createNetworkRequest(upnpDeviceDescriptor); + requestDeviceInformation(networkRequest, upnpDeviceDescriptor); + } } } @@ -210,15 +189,8 @@ void UpnpDiscovery::replyFinished(QNetworkReply *reply) } } - // check if we allready have the device in the list - bool isAlreadyInList = false; - foreach (UpnpDeviceDescriptor deviceDescriptor, m_deviceList) { - if (deviceDescriptor.uuid() == upnpDeviceDescriptor.uuid()) { - isAlreadyInList = true; - } - } - if (!isAlreadyInList) { - m_deviceList.append(upnpDeviceDescriptor); + foreach (UpnpDiscoveryRequest *upnpDiscoveryRequest, m_discoverRequests) { + upnpDiscoveryRequest->addDeviceDescriptor(upnpDeviceDescriptor); } break; } @@ -232,5 +204,9 @@ void UpnpDiscovery::replyFinished(QNetworkReply *reply) void UpnpDiscovery::discoverTimeout() { - emit discoveryFinished(m_deviceList, m_pluginId); + UpnpDiscoveryRequest *discoveryRequest = static_cast(sender()); + emit discoveryFinished(discoveryRequest->deviceList(), discoveryRequest->pluginId()); + + m_discoverRequests.removeOne(discoveryRequest); + delete discoveryRequest; } diff --git a/libguh/hardware/upnpdiscovery/upnpdiscovery.h b/libguh/hardware/upnpdiscovery/upnpdiscovery.h index 716f907c..f30ade46 100644 --- a/libguh/hardware/upnpdiscovery/upnpdiscovery.h +++ b/libguh/hardware/upnpdiscovery/upnpdiscovery.h @@ -30,31 +30,34 @@ #include #include +#include "upnpdiscoveryrequest.h" #include "upnpdevicedescriptor.h" #include "devicemanager.h" // reference: http://upnp.org/specs/arch/UPnP-arch-DeviceArchitecture-v1.1.pdf +class UpnpDiscoveryRequest; + class UpnpDiscovery : public QUdpSocket { Q_OBJECT public: explicit UpnpDiscovery(QObject *parent = 0); bool discoverDevices(const QString &searchTarget = "ssdp:all", const QString &userAgent = "", const PluginId &pluginId = PluginId()); + void sendToMulticast(const QByteArray &data); private: QHostAddress m_host; qint16 m_port; - QTimer *m_timer; - PluginId m_pluginId; - QString m_searchTarget; - QString m_userAgent; QNetworkAccessManager *m_networkAccessManager; - QHash m_informationRequestList; - QList m_deviceList; - void requestDeviceInformation(const UpnpDeviceDescriptor &upnpDeviceDescriptor); + QList m_discoverRequests; + QHash m_informationRequestList; + + void requestDeviceInformation(const QNetworkRequest &networkRequest, const UpnpDeviceDescriptor &upnpDeviceDescriptor); + +protected: signals: void discoveryFinished(const QList &deviceDescriptorList, const PluginId & pluginId); diff --git a/libguh/hardware/upnpdiscovery/upnpdiscoveryrequest.cpp b/libguh/hardware/upnpdiscovery/upnpdiscoveryrequest.cpp new file mode 100644 index 00000000..a1a16b05 --- /dev/null +++ b/libguh/hardware/upnpdiscovery/upnpdiscoveryrequest.cpp @@ -0,0 +1,73 @@ +#include "upnpdiscoveryrequest.h" + +UpnpDiscoveryRequest::UpnpDiscoveryRequest(UpnpDiscovery *upnpDiscovery, PluginId pluginId, QString searchTarget, QString userAgent): + QObject(upnpDiscovery), + m_upnpDiscovery(upnpDiscovery), + m_pluginId(pluginId), + m_searchTarget(searchTarget), + m_userAgent(userAgent) +{ + m_timer = new QTimer(this); + m_timer->setSingleShot(true); + connect(m_timer, &QTimer::timeout, this, &UpnpDiscoveryRequest::discoveryTimeout); +} + +void UpnpDiscoveryRequest::discover() +{ + QByteArray ssdpSearchMessage = QByteArray("M-SEARCH * HTTP/1.1\r\n" + "HOST:239.255.255.250:1900\r\n" + "MAN:\"ssdp:discover\"\r\n" + "MX:2\r\n" + "ST: " + m_searchTarget.toUtf8() + "\r\n" + "USR-AGENT: " + m_userAgent.toUtf8() + "\r\n\r\n"); + + m_upnpDiscovery->sendToMulticast(ssdpSearchMessage); + qDebug() << "--> UPnP discovery called."; + + m_timer->start(3000); +} + +void UpnpDiscoveryRequest::addDeviceDescriptor(const UpnpDeviceDescriptor &deviceDescriptor) +{ + + // check if we allready have the device in the list + bool isAlreadyInList = false; + foreach (UpnpDeviceDescriptor upnpDeviceDescriptor, m_deviceList) { + if (upnpDeviceDescriptor.uuid() == deviceDescriptor.uuid()) { + isAlreadyInList = true; + } + } + if (!isAlreadyInList) { + m_deviceList.append(deviceDescriptor); + } +} + +QNetworkRequest UpnpDiscoveryRequest::createNetworkRequest(UpnpDeviceDescriptor deviveDescriptor) +{ + QNetworkRequest deviceRequest; + deviceRequest.setUrl(deviveDescriptor.location()); + deviceRequest.setHeader(QNetworkRequest::ContentTypeHeader,QVariant("text/xml")); + deviceRequest.setHeader(QNetworkRequest::UserAgentHeader,QVariant(m_userAgent)); + + return deviceRequest; +} + +QList UpnpDiscoveryRequest::deviceList() const +{ + return m_deviceList; +} + +PluginId UpnpDiscoveryRequest::pluginId() const +{ + return m_pluginId; +} + +QString UpnpDiscoveryRequest::searchTarget() const +{ + return m_searchTarget; +} + +QString UpnpDiscoveryRequest::userAgent() const +{ + return m_userAgent; +} diff --git a/libguh/hardware/upnpdiscovery/upnpdiscoveryrequest.h b/libguh/hardware/upnpdiscovery/upnpdiscoveryrequest.h new file mode 100644 index 00000000..ab71ec8a --- /dev/null +++ b/libguh/hardware/upnpdiscovery/upnpdiscoveryrequest.h @@ -0,0 +1,43 @@ +#ifndef UPNPDISCOVERYREQUEST_H +#define UPNPDISCOVERYREQUEST_H + +#include +#include +#include "upnpdiscovery.h" +#include "upnpdevicedescriptor.h" +#include "typeutils.h" + +class UpnpDiscovery; + +class UpnpDiscoveryRequest : public QObject +{ + Q_OBJECT +public: + explicit UpnpDiscoveryRequest(UpnpDiscovery *upnpDiscovery, PluginId pluginId, QString searchTarget, QString userAgent); + + void discover(); + void addDeviceDescriptor(const UpnpDeviceDescriptor &deviceDescriptor); + QNetworkRequest createNetworkRequest(UpnpDeviceDescriptor deviveDescriptor); + QList deviceList() const; + + PluginId pluginId() const; + QString searchTarget() const; + QString userAgent() const; + +private: + UpnpDiscovery *m_upnpDiscovery; + QTimer *m_timer; + PluginId m_pluginId; + QString m_searchTarget; + QString m_userAgent; + + QList m_deviceList; + +signals: + void discoveryTimeout(); + +public slots: + +}; + +#endif // UPNPDISCOVERYREQUEST_H diff --git a/libguh/libguh.pro b/libguh/libguh.pro index c1a1a40d..dfb70655 100644 --- a/libguh/libguh.pro +++ b/libguh/libguh.pro @@ -34,6 +34,7 @@ SOURCES += plugin/device.cpp \ types/param.cpp \ types/paramdescriptor.cpp \ types/statedescriptor.cpp \ + hardware/upnpdiscovery/upnpdiscoveryrequest.cpp HEADERS += plugin/device.h \ plugin/deviceclass.h \ @@ -63,6 +64,4 @@ HEADERS += plugin/device.h \ types/paramdescriptor.h \ types/statedescriptor.h \ typeutils.h \ - hardware/upnpdiscovery/upnpdiscovery.h \ - hardware/upnpdiscovery/upnpdevice.h \ - hardware/upnpdiscovery/upnpdevicedescriptor.h + hardware/upnpdiscovery/upnpdiscoveryrequest.h diff --git a/plugins/deviceplugins/lgsmarttv/devicepluginlgsmarttv.cpp b/plugins/deviceplugins/lgsmarttv/devicepluginlgsmarttv.cpp index 77fd154a..b81eaedf 100644 --- a/plugins/deviceplugins/lgsmarttv/devicepluginlgsmarttv.cpp +++ b/plugins/deviceplugins/lgsmarttv/devicepluginlgsmarttv.cpp @@ -75,6 +75,14 @@ DeviceManager::DeviceError DevicePluginLgSmartTv::discoverDevices(const DeviceCl DeviceManager::DeviceSetupStatus DevicePluginLgSmartTv::setupDevice(Device *device) { + + foreach (Device* d, myDevices()) { + if (d->paramValue("uuid").toString() == device->paramValue("uuid").toString()) { + qWarning() << "LG Smart Tv (" << device->paramValue("model").toString() << ")" << "allready added...."; + return DeviceManager::DeviceSetupStatusFailure; + } + } + device->setName("LG Smart Tv (" + device->paramValue("model").toString() + ")"); UpnpDeviceDescriptor upnpDeviceDescriptor;