added support for multiple upnp discovery requests
This commit is contained in:
parent
a9117c9eb2
commit
4dee52a297
@ -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;
|
||||
}
|
||||
|
||||
@ -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);
|
||||
|
||||
73
libguh/hardware/upnpdiscovery/upnpdiscoveryrequest.cpp
Normal file
73
libguh/hardware/upnpdiscovery/upnpdiscoveryrequest.cpp
Normal 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;
|
||||
}
|
||||
43
libguh/hardware/upnpdiscovery/upnpdiscoveryrequest.h
Normal file
43
libguh/hardware/upnpdiscovery/upnpdiscoveryrequest.h
Normal 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
|
||||
@ -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
|
||||
|
||||
@ -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;
|
||||
|
||||
Reference in New Issue
Block a user