added support for multiple upnp discovery requests

This commit is contained in:
Simon Stürz 2015-02-12 17:35:25 +01:00 committed by Michael Zanetti
parent a9117c9eb2
commit 4dee52a297
6 changed files with 162 additions and 60 deletions

View File

@ -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<UpnpDiscoveryRequest*>(sender());
emit discoveryFinished(discoveryRequest->deviceList(), discoveryRequest->pluginId());
m_discoverRequests.removeOne(discoveryRequest);
delete discoveryRequest;
}

View File

@ -30,31 +30,34 @@
#include <QXmlStreamReader>
#include <QXmlStreamWriter>
#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<QNetworkReply*,UpnpDeviceDescriptor> m_informationRequestList;
QList<UpnpDeviceDescriptor> m_deviceList;
void requestDeviceInformation(const UpnpDeviceDescriptor &upnpDeviceDescriptor);
QList<UpnpDiscoveryRequest *> m_discoverRequests;
QHash<QNetworkReply*,UpnpDeviceDescriptor> m_informationRequestList;
void requestDeviceInformation(const QNetworkRequest &networkRequest, const UpnpDeviceDescriptor &upnpDeviceDescriptor);
protected:
signals:
void discoveryFinished(const QList<UpnpDeviceDescriptor> &deviceDescriptorList, const PluginId & pluginId);

View File

@ -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<UpnpDeviceDescriptor> 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;
}

View File

@ -0,0 +1,43 @@
#ifndef UPNPDISCOVERYREQUEST_H
#define UPNPDISCOVERYREQUEST_H
#include <QObject>
#include <QDebug>
#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<UpnpDeviceDescriptor> 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<UpnpDeviceDescriptor> m_deviceList;
signals:
void discoveryTimeout();
public slots:
};
#endif // UPNPDISCOVERYREQUEST_H

View File

@ -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

View File

@ -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;