added upnp discovery as hardware resource
This commit is contained in:
parent
6f72d39ec0
commit
30f5c44e08
@ -181,6 +181,9 @@ DeviceManager::DeviceManager(QObject *parent) :
|
||||
connect(m_radio433, &Radio433::dataReceived, this, &DeviceManager::radio433SignalReceived);
|
||||
m_radio433->enable();
|
||||
// TODO: error handling if no Radio433 detected (GPIO or network), disable radio433 plugins or something...
|
||||
|
||||
m_upnpDiscovery = new UpnpDiscovery(this);
|
||||
connect(m_upnpDiscovery, &UpnpDiscovery::discoveryFinished, this, &DeviceManager::upnpDiscoveryFinished);
|
||||
}
|
||||
|
||||
/*! Destructor of the DeviceManager. Each loaded \l{DevicePlugin} will be deleted. */
|
||||
@ -929,6 +932,15 @@ void DeviceManager::radio433SignalReceived(QList<int> rawData)
|
||||
}
|
||||
}
|
||||
|
||||
void DeviceManager::upnpDiscoveryFinished(const QList<UpnpDeviceDescriptor> &deviceDescriptorList, const PluginId &pluginId)
|
||||
{
|
||||
foreach (DevicePlugin *devicePlugin, m_devicePlugins) {
|
||||
if (devicePlugin->requiredHardware().testFlag(HardwareResourceUpnpDisovery) && devicePlugin->pluginId() == pluginId) {
|
||||
devicePlugin->upnpDiscoveryFinished(deviceDescriptorList);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DeviceManager::timerEvent()
|
||||
{
|
||||
foreach (Device *device, m_configuredDevices) {
|
||||
|
||||
@ -27,12 +27,16 @@
|
||||
#include "types/action.h"
|
||||
#include "types/vendor.h"
|
||||
|
||||
#include "hardware/upnpdiscovery/upnpdiscovery.h"
|
||||
#include "hardware/upnpdiscovery/upnpdevicedescriptor.h"
|
||||
|
||||
#include <QObject>
|
||||
#include <QTimer>
|
||||
|
||||
class Device;
|
||||
class DevicePlugin;
|
||||
class Radio433;
|
||||
class UpnpDiscovery;
|
||||
|
||||
class DeviceManager : public QObject
|
||||
{
|
||||
@ -43,7 +47,8 @@ public:
|
||||
HardwareResourceNone = 0x00,
|
||||
HardwareResourceRadio433 = 0x01,
|
||||
HardwareResourceRadio868 = 0x02,
|
||||
HardwareResourceTimer = 0x04
|
||||
HardwareResourceTimer = 0x04,
|
||||
HardwareResourceUpnpDisovery = 0x08
|
||||
};
|
||||
Q_DECLARE_FLAGS(HardwareResources, HardwareResource)
|
||||
|
||||
@ -126,6 +131,7 @@ private slots:
|
||||
void slotDeviceStateValueChanged(const QUuid &stateTypeId, const QVariant &value);
|
||||
|
||||
void radio433SignalReceived(QList<int> rawData);
|
||||
void upnpDiscoveryFinished(const QList<UpnpDeviceDescriptor> &deviceDescriptorList, const PluginId &pluginId);
|
||||
void timerEvent();
|
||||
|
||||
private:
|
||||
@ -152,6 +158,7 @@ private:
|
||||
Radio433* m_radio433;
|
||||
QTimer m_pluginTimer;
|
||||
QList<Device*> m_pluginTimerUsers;
|
||||
UpnpDiscovery* m_upnpDiscovery;
|
||||
|
||||
QHash<QUuid, QPair<DeviceClassId, ParamList> > m_pairingsJustAdd;
|
||||
QHash<QUuid, QPair<DeviceClassId, DeviceDescriptorId> > m_pairingsDiscovery;
|
||||
|
||||
108
libguh/hardware/upnpdiscovery/upnpdevice.cpp
Normal file
108
libguh/hardware/upnpdiscovery/upnpdevice.cpp
Normal file
@ -0,0 +1,108 @@
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
* *
|
||||
* 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 "upnpdevice.h"
|
||||
|
||||
UpnpDevice::UpnpDevice(QObject *parent, UpnpDeviceDescriptor upnpDeviceDescriptor) :
|
||||
QObject(parent)
|
||||
{
|
||||
m_location = upnpDeviceDescriptor.location();
|
||||
m_hostAddress = upnpDeviceDescriptor.hostAddress();
|
||||
m_port = upnpDeviceDescriptor.port();
|
||||
m_deviceType = upnpDeviceDescriptor.deviceType();
|
||||
m_friendlyName = upnpDeviceDescriptor.friendlyName();
|
||||
m_manufacturer = upnpDeviceDescriptor.manufacturer();
|
||||
m_manufacturerURL = upnpDeviceDescriptor.manufacturerURL();
|
||||
m_modelDescription = upnpDeviceDescriptor.modelDescription();
|
||||
m_modelName = upnpDeviceDescriptor.modelName();
|
||||
m_modelNumber = upnpDeviceDescriptor.modelNumber();
|
||||
m_modelURL = upnpDeviceDescriptor.modelURL();
|
||||
m_serialNumber = upnpDeviceDescriptor.serialNumber();
|
||||
m_uuid = upnpDeviceDescriptor.uuid();
|
||||
m_upc = upnpDeviceDescriptor.upc();
|
||||
}
|
||||
|
||||
QUrl UpnpDevice::location()
|
||||
{
|
||||
return m_location;
|
||||
}
|
||||
|
||||
QHostAddress UpnpDevice::hostAddress() const
|
||||
{
|
||||
return m_hostAddress;
|
||||
}
|
||||
|
||||
int UpnpDevice::port() const
|
||||
{
|
||||
return m_port;
|
||||
}
|
||||
|
||||
QString UpnpDevice::deviceType() const
|
||||
{
|
||||
return m_deviceType;
|
||||
}
|
||||
|
||||
QString UpnpDevice::friendlyName() const
|
||||
{
|
||||
return m_friendlyName;
|
||||
}
|
||||
|
||||
QString UpnpDevice::manufacturer() const
|
||||
{
|
||||
return m_manufacturer;
|
||||
}
|
||||
|
||||
QUrl UpnpDevice::manufacturerURL() const
|
||||
{
|
||||
return m_manufacturerURL;
|
||||
}
|
||||
|
||||
QString UpnpDevice::modelDescription() const
|
||||
{
|
||||
return m_modelDescription;
|
||||
}
|
||||
|
||||
QString UpnpDevice::modelName() const
|
||||
{
|
||||
return m_modelName;
|
||||
}
|
||||
|
||||
QString UpnpDevice::modelNumber() const
|
||||
{
|
||||
return m_modelNumber;
|
||||
}
|
||||
|
||||
QUrl UpnpDevice::modelURL() const
|
||||
{
|
||||
return m_modelURL;
|
||||
}
|
||||
|
||||
QString UpnpDevice::serialNumber() const
|
||||
{
|
||||
return m_serialNumber;
|
||||
}
|
||||
|
||||
QString UpnpDevice::uuid() const
|
||||
{
|
||||
return m_uuid;
|
||||
}
|
||||
|
||||
QString UpnpDevice::upc() const
|
||||
{
|
||||
return m_upc;
|
||||
}
|
||||
70
libguh/hardware/upnpdiscovery/upnpdevice.h
Normal file
70
libguh/hardware/upnpdiscovery/upnpdevice.h
Normal file
@ -0,0 +1,70 @@
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
* *
|
||||
* 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 UPNPDEVICE_H
|
||||
#define UPNPDEVICE_H
|
||||
|
||||
#include <QObject>
|
||||
|
||||
#include "upnpdevicedescriptor.h"
|
||||
|
||||
class UpnpDevice : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit UpnpDevice(QObject *parent = 0, UpnpDeviceDescriptor upnpDeviceDescriptor = UpnpDeviceDescriptor());
|
||||
|
||||
QUrl location();
|
||||
QHostAddress hostAddress() const;
|
||||
int port() const;
|
||||
QString deviceType() const;
|
||||
QString friendlyName() const;
|
||||
QString manufacturer() const;
|
||||
QUrl manufacturerURL() const;
|
||||
QString modelDescription() const;
|
||||
QString modelName() const;
|
||||
QString modelNumber() const;
|
||||
QUrl modelURL() const;
|
||||
QString serialNumber() const;
|
||||
QString uuid() const;
|
||||
QString upc() const;
|
||||
|
||||
|
||||
private:
|
||||
QUrl m_location;
|
||||
QHostAddress m_hostAddress;
|
||||
int m_port;
|
||||
QString m_deviceType;
|
||||
QString m_friendlyName;
|
||||
QString m_manufacturer;
|
||||
QUrl m_manufacturerURL;
|
||||
QString m_modelDescription;
|
||||
QString m_modelName;
|
||||
QString m_modelNumber;
|
||||
QUrl m_modelURL;
|
||||
QString m_serialNumber;
|
||||
QString m_uuid;
|
||||
QString m_upc;
|
||||
|
||||
signals:
|
||||
|
||||
public slots:
|
||||
|
||||
};
|
||||
|
||||
#endif // UPNPDEVICE_H
|
||||
183
libguh/hardware/upnpdiscovery/upnpdevicedescriptor.cpp
Normal file
183
libguh/hardware/upnpdiscovery/upnpdevicedescriptor.cpp
Normal file
@ -0,0 +1,183 @@
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
* *
|
||||
* 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 "upnpdevicedescriptor.h"
|
||||
|
||||
UpnpDeviceDescriptor::UpnpDeviceDescriptor()
|
||||
{
|
||||
}
|
||||
|
||||
void UpnpDeviceDescriptor::setLocation(const QUrl &location)
|
||||
{
|
||||
m_location = location;
|
||||
}
|
||||
|
||||
QUrl UpnpDeviceDescriptor::location() const
|
||||
{
|
||||
return m_location;
|
||||
}
|
||||
|
||||
void UpnpDeviceDescriptor::setHostAddress(const QHostAddress &hostAddress)
|
||||
{
|
||||
m_hostAddress = hostAddress;
|
||||
}
|
||||
|
||||
QHostAddress UpnpDeviceDescriptor::hostAddress() const
|
||||
{
|
||||
return m_hostAddress;
|
||||
}
|
||||
|
||||
void UpnpDeviceDescriptor::setPort(const int &port)
|
||||
{
|
||||
m_port = port;
|
||||
}
|
||||
|
||||
int UpnpDeviceDescriptor::port() const
|
||||
{
|
||||
return m_port;
|
||||
}
|
||||
|
||||
void UpnpDeviceDescriptor::setDeviceType(const QString &deviceType)
|
||||
{
|
||||
m_deviceType = deviceType;
|
||||
}
|
||||
|
||||
QString UpnpDeviceDescriptor::deviceType() const
|
||||
{
|
||||
return m_deviceType;
|
||||
}
|
||||
|
||||
void UpnpDeviceDescriptor::setFriendlyName(const QString &friendlyName)
|
||||
{
|
||||
m_friendlyName = friendlyName;
|
||||
}
|
||||
|
||||
QString UpnpDeviceDescriptor::friendlyName() const
|
||||
{
|
||||
return m_friendlyName;
|
||||
}
|
||||
|
||||
void UpnpDeviceDescriptor::setManufacturer(const QString &manufacturer)
|
||||
{
|
||||
m_manufacturer = manufacturer;
|
||||
}
|
||||
|
||||
QString UpnpDeviceDescriptor::manufacturer() const
|
||||
{
|
||||
return m_manufacturer;
|
||||
}
|
||||
|
||||
void UpnpDeviceDescriptor::setManufacturerURL(const QUrl &manufacturerURL)
|
||||
{
|
||||
m_manufacturerURL = manufacturerURL;
|
||||
}
|
||||
|
||||
QUrl UpnpDeviceDescriptor::manufacturerURL() const
|
||||
{
|
||||
return m_manufacturerURL;
|
||||
}
|
||||
|
||||
void UpnpDeviceDescriptor::setModelDescription(const QString &modelDescription)
|
||||
{
|
||||
m_modelDescription = modelDescription;
|
||||
}
|
||||
|
||||
QString UpnpDeviceDescriptor::modelDescription() const
|
||||
{
|
||||
return m_modelDescription;
|
||||
}
|
||||
|
||||
void UpnpDeviceDescriptor::setModelName(const QString &modelName)
|
||||
{
|
||||
m_modelName = modelName;
|
||||
}
|
||||
|
||||
QString UpnpDeviceDescriptor::modelName() const
|
||||
{
|
||||
return m_modelName;
|
||||
}
|
||||
|
||||
void UpnpDeviceDescriptor::setModelNumber(const QString &modelNumber)
|
||||
{
|
||||
m_modelNumber = modelNumber;
|
||||
}
|
||||
|
||||
QString UpnpDeviceDescriptor::modelNumber() const
|
||||
{
|
||||
return m_modelNumber;
|
||||
}
|
||||
|
||||
void UpnpDeviceDescriptor::setModelURL(const QUrl &modelURL)
|
||||
{
|
||||
m_modelURL = modelURL;
|
||||
}
|
||||
|
||||
QUrl UpnpDeviceDescriptor::modelURL() const
|
||||
{
|
||||
return m_modelURL;
|
||||
}
|
||||
|
||||
void UpnpDeviceDescriptor::setSerialNumber(const QString &serialNumber)
|
||||
{
|
||||
m_serialNumber = serialNumber;
|
||||
}
|
||||
|
||||
QString UpnpDeviceDescriptor::serialNumber() const
|
||||
{
|
||||
return m_serialNumber;
|
||||
}
|
||||
|
||||
void UpnpDeviceDescriptor::setUuid(const QString &uuid)
|
||||
{
|
||||
m_uuid = uuid;
|
||||
}
|
||||
|
||||
QString UpnpDeviceDescriptor::uuid() const
|
||||
{
|
||||
return m_uuid;
|
||||
}
|
||||
|
||||
void UpnpDeviceDescriptor::setUpc(const QString &upc)
|
||||
{
|
||||
m_upc = upc;
|
||||
}
|
||||
|
||||
QString UpnpDeviceDescriptor::upc() const
|
||||
{
|
||||
return m_upc;
|
||||
}
|
||||
|
||||
QDebug operator<<(QDebug debug, const UpnpDeviceDescriptor &upnpDeviceDescriptor)
|
||||
{
|
||||
debug << "----------------------------------------------\n";
|
||||
debug << "UPnP device on " << upnpDeviceDescriptor.hostAddress().toString() << upnpDeviceDescriptor.port() << "\n";
|
||||
debug << "location | " << upnpDeviceDescriptor.location() << "\n";
|
||||
debug << "friendly name | " << upnpDeviceDescriptor.friendlyName() << "\n";
|
||||
debug << "manufacturer | " << upnpDeviceDescriptor.manufacturer() << "\n";
|
||||
debug << "manufacturer URL | " << upnpDeviceDescriptor.manufacturerURL().toString() << "\n";
|
||||
debug << "device type | " << upnpDeviceDescriptor.deviceType() << "\n";
|
||||
debug << "model name | " << upnpDeviceDescriptor.modelName() << "\n";
|
||||
debug << "model number | " << upnpDeviceDescriptor.modelNumber() << "\n";
|
||||
debug << "model description | " << upnpDeviceDescriptor.modelDescription() << "\n";
|
||||
debug << "model URL | " << upnpDeviceDescriptor.modelURL().toString() << "\n";
|
||||
debug << "serial number | " << upnpDeviceDescriptor.serialNumber() << "\n";
|
||||
debug << "UUID | " << upnpDeviceDescriptor.uuid() << "\n";
|
||||
debug << "UPC | " << upnpDeviceDescriptor.upc() << "\n\n";
|
||||
|
||||
return debug;
|
||||
}
|
||||
96
libguh/hardware/upnpdiscovery/upnpdevicedescriptor.h
Normal file
96
libguh/hardware/upnpdiscovery/upnpdevicedescriptor.h
Normal file
@ -0,0 +1,96 @@
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
* *
|
||||
* 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 UPNPDEVICEDESCRIPTOR_H
|
||||
#define UPNPDEVICEDESCRIPTOR_H
|
||||
|
||||
#include <QDebug>
|
||||
#include <QHostAddress>
|
||||
#include <QUrl>
|
||||
|
||||
// reference: http://upnp.org/specs/arch/UPnP-arch-DeviceArchitecture-v1.1.pdf
|
||||
|
||||
class UpnpDeviceDescriptor
|
||||
{
|
||||
public:
|
||||
explicit UpnpDeviceDescriptor();
|
||||
|
||||
void setLocation(const QUrl &location);
|
||||
QUrl location() const;
|
||||
|
||||
void setHostAddress(const QHostAddress &hostAddress);
|
||||
QHostAddress hostAddress() const;
|
||||
|
||||
void setPort(const int &port);
|
||||
int port() const;
|
||||
|
||||
void setDeviceType(const QString &deviceType);
|
||||
QString deviceType() const;
|
||||
|
||||
void setFriendlyName(const QString &friendlyName);
|
||||
QString friendlyName() const;
|
||||
|
||||
void setManufacturer(const QString &manufacturer);
|
||||
QString manufacturer() const;
|
||||
|
||||
void setManufacturerURL(const QUrl &manufacturerURL);
|
||||
QUrl manufacturerURL() const;
|
||||
|
||||
void setModelDescription(const QString &modelDescription);
|
||||
QString modelDescription() const;
|
||||
|
||||
void setModelName(const QString &modelName);
|
||||
QString modelName() const;
|
||||
|
||||
void setModelNumber(const QString &modelNumber);
|
||||
QString modelNumber() const;
|
||||
|
||||
void setModelURL(const QUrl &modelURL);
|
||||
QUrl modelURL() const;
|
||||
|
||||
void setSerialNumber(const QString &serialNumber);
|
||||
QString serialNumber() const;
|
||||
|
||||
void setUuid(const QString &uuid);
|
||||
QString uuid() const;
|
||||
|
||||
void setUpc(const QString &upc);
|
||||
QString upc() const;
|
||||
|
||||
|
||||
private:
|
||||
QUrl m_location;
|
||||
QHostAddress m_hostAddress;
|
||||
int m_port;
|
||||
QString m_deviceType;
|
||||
QString m_friendlyName;
|
||||
QString m_manufacturer;
|
||||
QUrl m_manufacturerURL;
|
||||
QString m_modelDescription;
|
||||
QString m_modelName;
|
||||
QString m_modelNumber;
|
||||
QUrl m_modelURL;
|
||||
QString m_serialNumber;
|
||||
QString m_uuid;
|
||||
QString m_upc;
|
||||
};
|
||||
|
||||
Q_DECLARE_METATYPE(UpnpDeviceDescriptor)
|
||||
QDebug operator<< (QDebug debug, const UpnpDeviceDescriptor &upnpDeviceDescriptor);
|
||||
|
||||
#endif // UPNPDEVICEDESCRIPTOR_H
|
||||
221
libguh/hardware/upnpdiscovery/upnpdiscovery.cpp
Normal file
221
libguh/hardware/upnpdiscovery/upnpdiscovery.cpp
Normal file
@ -0,0 +1,221 @@
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
* *
|
||||
* 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 "upnpdiscovery.h"
|
||||
|
||||
UpnpDiscovery::UpnpDiscovery(QObject *parent) :
|
||||
QUdpSocket(parent)
|
||||
{
|
||||
// bind udp socket and join multicast group
|
||||
m_port = 1900;
|
||||
m_host = QHostAddress("239.255.255.250");
|
||||
|
||||
setSocketOption(QAbstractSocket::MulticastTtlOption,QVariant(1));
|
||||
setSocketOption(QAbstractSocket::MulticastLoopbackOption,QVariant(1));
|
||||
|
||||
if(!bind(QHostAddress::AnyIPv4,m_port,QUdpSocket::ShareAddress)){
|
||||
qWarning() << "ERROR: UPnP discovery could not bind to port " << m_port;
|
||||
return;
|
||||
}
|
||||
|
||||
if(!joinMulticastGroup(m_host)){
|
||||
qWarning() << "ERROR: UPnP discovery could not join multicast group " << m_host;
|
||||
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(this,SIGNAL(error(QAbstractSocket::SocketError)),this,SLOT(error(QAbstractSocket::SocketError)));
|
||||
connect(this, &UpnpDiscovery::readyRead, this, &UpnpDiscovery::readData);
|
||||
|
||||
qDebug() << "--> Successfully created UPnPDiscovery.";
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
m_searchTarget = searchTarget;
|
||||
m_userAgent = userAgent;
|
||||
m_pluginId = pluginId;
|
||||
|
||||
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");
|
||||
|
||||
writeDatagram(ssdpSearchMessage,m_host,m_port);
|
||||
|
||||
m_timer->start(3000);
|
||||
return true;
|
||||
}
|
||||
|
||||
void UpnpDiscovery::requestDeviceInformation(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);
|
||||
m_informationRequestList.insert(replay, upnpDeviceDescriptor);
|
||||
}
|
||||
|
||||
void UpnpDiscovery::error(QAbstractSocket::SocketError error)
|
||||
{
|
||||
qWarning() << errorString() << error;
|
||||
}
|
||||
|
||||
void UpnpDiscovery::readData()
|
||||
{
|
||||
QByteArray data;
|
||||
QHostAddress hostAddress;
|
||||
QUrl location;
|
||||
|
||||
// read the answere from the multicast
|
||||
while (hasPendingDatagrams()) {
|
||||
data.resize(pendingDatagramSize());
|
||||
readDatagram(data.data(), data.size(), &hostAddress);
|
||||
}
|
||||
// qDebug() << "-----------------------";
|
||||
// qDebug() << data;
|
||||
|
||||
// if the data contains the HTTP OK header...
|
||||
if(data.contains("HTTP/1.1 200 OK")){
|
||||
const QStringList lines = QString(data).split("\r\n");
|
||||
foreach( const QString& line, lines){
|
||||
int separatorIndex = line.indexOf(':');
|
||||
QString key = line.left(separatorIndex).toUpper();
|
||||
QString value = line.mid(separatorIndex+1).trimmed();
|
||||
|
||||
// get location
|
||||
if(key.contains("LOCATION")){
|
||||
location = QUrl(value);
|
||||
}
|
||||
}
|
||||
|
||||
UpnpDeviceDescriptor upnpDeviceDescriptor;
|
||||
upnpDeviceDescriptor.setLocation(location);
|
||||
upnpDeviceDescriptor.setHostAddress(hostAddress);
|
||||
upnpDeviceDescriptor.setPort(location.port());
|
||||
|
||||
requestDeviceInformation(upnpDeviceDescriptor);
|
||||
}
|
||||
}
|
||||
|
||||
void UpnpDiscovery::replyFinished(QNetworkReply *reply)
|
||||
{
|
||||
int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
||||
|
||||
switch (status) {
|
||||
case(200):{
|
||||
QByteArray data = reply->readAll();
|
||||
UpnpDeviceDescriptor upnpDeviceDescriptor = m_informationRequestList.take(reply);
|
||||
|
||||
// parse XML data
|
||||
QXmlStreamReader xml(data);
|
||||
while(!xml.atEnd() && !xml.hasError()){
|
||||
xml.readNext();
|
||||
if(xml.isStartDocument()){
|
||||
continue;
|
||||
}
|
||||
if(xml.isStartElement()){
|
||||
if(xml.name().toString() == "device"){
|
||||
while(!xml.atEnd()){
|
||||
if(xml.name() == "deviceType" && xml.isStartElement()){
|
||||
upnpDeviceDescriptor.setDeviceType(xml.readElementText());
|
||||
}
|
||||
if(xml.name() == "friendlyName" && xml.isStartElement()){
|
||||
upnpDeviceDescriptor.setFriendlyName(xml.readElementText());
|
||||
}
|
||||
if(xml.name() == "manufacturer" && xml.isStartElement()){
|
||||
upnpDeviceDescriptor.setManufacturer(xml.readElementText());
|
||||
}
|
||||
if(xml.name() == "manufacturerURL" && xml.isStartElement()){
|
||||
upnpDeviceDescriptor.setManufacturerURL(QUrl(xml.readElementText()));
|
||||
}
|
||||
if(xml.name() == "modelDescription" && xml.isStartElement()){
|
||||
upnpDeviceDescriptor.setModelDescription(xml.readElementText());
|
||||
}
|
||||
if(xml.name() == "modelName" && xml.isStartElement()){
|
||||
upnpDeviceDescriptor.setModelName(xml.readElementText());
|
||||
}
|
||||
if(xml.name() == "modelNumber" && xml.isStartElement()){
|
||||
upnpDeviceDescriptor.setModelNumber(xml.readElementText());
|
||||
}
|
||||
if(xml.name() == "modelURL" && xml.isStartElement()){
|
||||
upnpDeviceDescriptor.setModelURL(QUrl(xml.readElementText()));
|
||||
}
|
||||
if(xml.name() == "serialNumber" && xml.isStartElement()){
|
||||
upnpDeviceDescriptor.setSerialNumber(xml.readElementText());
|
||||
}
|
||||
if(xml.name() == "UDN" && xml.isStartElement()){
|
||||
upnpDeviceDescriptor.setUuid(xml.readElementText());
|
||||
}
|
||||
if(xml.name() == "UPC" && xml.isStartElement()){
|
||||
upnpDeviceDescriptor.setUpc(xml.readElementText());
|
||||
}
|
||||
xml.readNext();
|
||||
}
|
||||
xml.readNext();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
qWarning() << "HTTP request error " << status;
|
||||
m_informationRequestList.remove(reply);
|
||||
}
|
||||
|
||||
reply->deleteLater();
|
||||
}
|
||||
|
||||
void UpnpDiscovery::discoverTimeout()
|
||||
{
|
||||
emit discoveryFinished(m_deviceList, m_pluginId);
|
||||
}
|
||||
71
libguh/hardware/upnpdiscovery/upnpdiscovery.h
Normal file
71
libguh/hardware/upnpdiscovery/upnpdiscovery.h
Normal file
@ -0,0 +1,71 @@
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
* *
|
||||
* 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 UPNPDISCOVERY_H
|
||||
#define UPNPDISCOVERY_H
|
||||
|
||||
#include <QUdpSocket>
|
||||
#include <QHostAddress>
|
||||
#include <QTimer>
|
||||
#include <QTimer>
|
||||
#include <QNetworkAccessManager>
|
||||
#include <QNetworkReply>
|
||||
#include <QNetworkRequest>
|
||||
#include <QUrl>
|
||||
#include <QXmlStreamReader>
|
||||
#include <QXmlStreamWriter>
|
||||
|
||||
#include "upnpdevicedescriptor.h"
|
||||
#include "devicemanager.h"
|
||||
|
||||
// reference: http://upnp.org/specs/arch/UPnP-arch-DeviceArchitecture-v1.1.pdf
|
||||
|
||||
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());
|
||||
|
||||
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);
|
||||
|
||||
signals:
|
||||
void discoveryFinished(const QList<UpnpDeviceDescriptor> &deviceDescriptorList, const PluginId & pluginId);
|
||||
|
||||
private slots:
|
||||
void error(QAbstractSocket::SocketError error);
|
||||
void readData();
|
||||
void replyFinished(QNetworkReply *reply);
|
||||
void discoverTimeout();
|
||||
|
||||
public slots:
|
||||
};
|
||||
|
||||
#endif // UPNPDISCOVERY_H
|
||||
@ -31,6 +31,9 @@ SOURCES += plugin/device.cpp \
|
||||
types/param.cpp \
|
||||
types/paramdescriptor.cpp \
|
||||
types/statedescriptor.cpp \
|
||||
hardware/upnpdiscovery/upnpdiscovery.cpp \
|
||||
hardware/upnpdiscovery/upnpdevice.cpp \
|
||||
hardware/upnpdiscovery/upnpdevicedescriptor.cpp
|
||||
|
||||
HEADERS += plugin/device.h \
|
||||
plugin/deviceclass.h \
|
||||
@ -57,4 +60,6 @@ HEADERS += plugin/device.h \
|
||||
types/paramdescriptor.h \
|
||||
types/statedescriptor.h \
|
||||
typeutils.h \
|
||||
|
||||
hardware/upnpdiscovery/upnpdiscovery.h \
|
||||
hardware/upnpdiscovery/upnpdevice.h \
|
||||
hardware/upnpdiscovery/upnpdevicedescriptor.h
|
||||
|
||||
@ -47,7 +47,15 @@
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn DeviceManager::DeviceError DevicePlugin::executeAction(Device *device, const Action &action)
|
||||
\fn void DevicePlugin::upnpDiscoveryFinished(QList<UpnpDevice> deviceList)
|
||||
If the plugin has requested the upnp \a deviceList using \l{DevicePlugin::upnpDiscover(QString searchTarget)},
|
||||
this slot will be called after 3 seconds (search timeout). The list will contain all devices available on in
|
||||
the network, which responded to the given search target string
|
||||
\sa DevicePlugin::upnpDiscover()
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn void DevicePlugin::executeAction(Device *device, const Action &action)
|
||||
This will be called to actually execute actions on the hardware. The \{Device} and
|
||||
the \{Action} are contained in the \a device and \a action parameters.
|
||||
Return the appropriate \l{DeviceManager::DeviceError}{DeviceError}.
|
||||
@ -117,6 +125,7 @@
|
||||
|
||||
#include "devicemanager.h"
|
||||
#include "hardware/radio433/radio433.h"
|
||||
#include "hardware/upnpdiscovery/upnpdiscovery.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QFileInfo>
|
||||
@ -507,13 +516,16 @@ bool DevicePlugin::transmitData(int delay, QList<int> rawData, int repetitions)
|
||||
return false;
|
||||
}
|
||||
|
||||
QStringList DevicePlugin::verifyFields(const QStringList &fields, const QJsonObject &value) const
|
||||
/*!
|
||||
Starts a SSDP search for a certain \a searchTarget (ST). Certain UPnP devices need a special ST (i.e. "udap:rootservice"
|
||||
for LG Smart Tv's), otherwise they will not respond on the SSDP search. Each HTTP request to this device needs sometimes
|
||||
also a special \a userAgent, which will be written into the HTTP header.
|
||||
\sa DevicePlugin::requiredHardware(), DevicePlugin::upnpDiscoveryFinished()
|
||||
*/
|
||||
|
||||
void DevicePlugin::upnpDiscover(QString searchTarget, QString userAgent)
|
||||
{
|
||||
QStringList ret;
|
||||
foreach (const QString &field, fields) {
|
||||
if (!value.contains(field)) {
|
||||
ret << field;
|
||||
}
|
||||
if(requiredHardware() == DeviceManager::HardwareResourceUpnpDisovery){
|
||||
deviceManager()->m_upnpDiscovery->discoverDevices(searchTarget, userAgent, pluginId());
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -61,6 +61,7 @@ public:
|
||||
// Hardware input
|
||||
virtual void radioData(const QList<int> &rawData) {Q_UNUSED(rawData)}
|
||||
virtual void guhTimer() {}
|
||||
virtual void upnpDiscoveryFinished(const QList<UpnpDeviceDescriptor> &upnpDeviceDescriptorList) {Q_UNUSED(upnpDeviceDescriptorList)}
|
||||
|
||||
// Configuration
|
||||
virtual QList<ParamType> configurationDescription() const;
|
||||
@ -89,7 +90,8 @@ protected:
|
||||
QList<Device*> myDevices() const;
|
||||
Device* findDeviceByParams(const ParamList ¶ms) const;
|
||||
|
||||
bool transmitData(int delay, QList<int> rawData, int repetitions = 10);
|
||||
bool transmitData(int delay, QList<int> rawData);
|
||||
void upnpDiscover(QString searchTarget = "ssdp:all", QString userAgent = QString());
|
||||
|
||||
private:
|
||||
void initPlugin(const QJsonObject &metaData, DeviceManager *deviceManager);
|
||||
|
||||
@ -3,7 +3,9 @@ include(../guh.pri)
|
||||
TEMPLATE = lib
|
||||
CONFIG += plugin
|
||||
|
||||
INCLUDEPATH += $$top_srcdir/libguh
|
||||
QT += network
|
||||
|
||||
INCLUDEPATH += ../../../libguh
|
||||
LIBS += -L../../../libguh -lguh
|
||||
|
||||
infofile.output = plugininfo.h
|
||||
|
||||
Reference in New Issue
Block a user