Continue migrating hardware resources

This commit is contained in:
Simon Stürz 2017-11-13 15:46:32 +01:00 committed by Michael Zanetti
parent ac436b0751
commit 66b537cadc
15 changed files with 289 additions and 303 deletions

View File

@ -185,6 +185,8 @@
#include "guhsettings.h"
#include "unistd.h"
#include "plugintimer.h"
#include <QPluginLoader>
#include <QStaticPlugin>
#include <QtPlugin>
@ -205,10 +207,9 @@ DeviceManager::DeviceManager(const QLocale &locale, QObject *parent) :
m_hardwareManager = new HardwareManager(this);
connect(m_hardwareManager->pluginTimer(), &PluginTimer::timerEvent, this, &DeviceManager::timerEvent);
connect(m_hardwareManager->networkManager(), &NetworkAccessManager::replyReady, this, &DeviceManager::replyReady);
connect(m_hardwareManager->upnpDiscovery(), &UpnpDiscovery::discoveryFinished, this, &DeviceManager::upnpDiscoveryFinished);
connect(m_hardwareManager->upnpDiscovery(), &UpnpDiscovery::upnpNotify, this, &DeviceManager::upnpNotifyReceived);
connect(m_hardwareManager->bluetoothScanner(), &BluetoothScanner::bluetoothDiscoveryFinished, this, &DeviceManager::bluetoothDiscoveryFinished);
// connect(m_hardwareManager->upnpDiscovery(), &UpnpDiscovery::discoveryFinished, this, &DeviceManager::upnpDiscoveryFinished);
// connect(m_hardwareManager->upnpDiscovery(), &UpnpDiscovery::upnpNotify, this, &DeviceManager::upnpNotifyReceived);
// connect(m_hardwareManager->bluetoothScanner(), &BluetoothScanner::bluetoothDiscoveryFinished, this, &DeviceManager::bluetoothDiscoveryFinished);
// Give hardware a chance to start up before loading plugins etc.
QMetaObject::invokeMethod(this, "loadPlugins", Qt::QueuedConnection);
@ -1424,63 +1425,63 @@ void DeviceManager::slotDeviceStateValueChanged(const QUuid &stateTypeId, const
emit eventTriggered(event);
}
void DeviceManager::radio433SignalReceived(QList<int> rawData)
{
QList<DevicePlugin*> targetPlugins;
//void DeviceManager::radio433SignalReceived(QList<int> rawData)
//{
// QList<DevicePlugin*> targetPlugins;
foreach (Device *device, m_configuredDevices) {
DeviceClass deviceClass = m_supportedDevices.value(device->deviceClassId());
DevicePlugin *plugin = m_devicePlugins.value(deviceClass.pluginId());
if (plugin->requiredHardware().testFlag(HardwareResource::TypeRadio433) && !targetPlugins.contains(plugin)) {
targetPlugins.append(plugin);
}
}
foreach (DevicePlugin *plugin, m_discoveringPlugins) {
if (plugin->requiredHardware().testFlag(HardwareResource::TypeRadio433) && !targetPlugins.contains(plugin)) {
targetPlugins.append(plugin);
}
}
// foreach (Device *device, m_configuredDevices) {
// DeviceClass deviceClass = m_supportedDevices.value(device->deviceClassId());
// DevicePlugin *plugin = m_devicePlugins.value(deviceClass.pluginId());
// if (plugin->requiredHardware().testFlag(HardwareResource::TypeRadio433) && !targetPlugins.contains(plugin)) {
// targetPlugins.append(plugin);
// }
// }
// foreach (DevicePlugin *plugin, m_discoveringPlugins) {
// if (plugin->requiredHardware().testFlag(HardwareResource::TypeRadio433) && !targetPlugins.contains(plugin)) {
// targetPlugins.append(plugin);
// }
// }
foreach (DevicePlugin *plugin, targetPlugins) {
plugin->radioData(rawData);
}
}
// foreach (DevicePlugin *plugin, targetPlugins) {
// plugin->radioData(rawData);
// }
//}
void DeviceManager::replyReady(const PluginId &pluginId, QNetworkReply *reply)
{
foreach (DevicePlugin *devicePlugin, m_devicePlugins) {
if (devicePlugin->requiredHardware().testFlag(HardwareResource::TypeNetworkManager) && devicePlugin->pluginId() == pluginId) {
devicePlugin->networkManagerReplyReady(reply);
}
}
}
//void DeviceManager::replyReady(const PluginId &pluginId, QNetworkReply *reply)
//{
// foreach (DevicePlugin *devicePlugin, m_devicePlugins) {
// if (devicePlugin->requiredHardware().testFlag(HardwareResource::TypeNetworkManager) && devicePlugin->pluginId() == pluginId) {
// devicePlugin->networkManagerReplyReady(reply);
// }
// }
//}
void DeviceManager::upnpDiscoveryFinished(const QList<UpnpDeviceDescriptor> &deviceDescriptorList, const PluginId &pluginId)
{
foreach (DevicePlugin *devicePlugin, m_devicePlugins) {
if (devicePlugin->requiredHardware().testFlag(HardwareResource::TypeUpnpDisovery) && devicePlugin->pluginId() == pluginId) {
devicePlugin->upnpDiscoveryFinished(deviceDescriptorList);
}
}
}
//void DeviceManager::upnpDiscoveryFinished(const QList<UpnpDeviceDescriptor> &deviceDescriptorList, const PluginId &pluginId)
//{
// foreach (DevicePlugin *devicePlugin, m_devicePlugins) {
// if (devicePlugin->requiredHardware().testFlag(HardwareResource::TypeUpnpDisovery) && devicePlugin->pluginId() == pluginId) {
// devicePlugin->upnpDiscoveryFinished(deviceDescriptorList);
// }
// }
//}
void DeviceManager::upnpNotifyReceived(const QByteArray &notifyData)
{
foreach (DevicePlugin *devicePlugin, m_devicePlugins) {
if (devicePlugin->requiredHardware().testFlag(HardwareResource::TypeUpnpDisovery)) {
devicePlugin->upnpNotifyReceived(notifyData);
}
}
}
//void DeviceManager::upnpNotifyReceived(const QByteArray &notifyData)
//{
// foreach (DevicePlugin *devicePlugin, m_devicePlugins) {
// if (devicePlugin->requiredHardware().testFlag(HardwareResource::TypeUpnpDisovery)) {
// devicePlugin->upnpNotifyReceived(notifyData);
// }
// }
//}
void DeviceManager::bluetoothDiscoveryFinished(const PluginId &pluginId, const QList<QBluetoothDeviceInfo> &deviceInfos)
{
foreach (DevicePlugin *devicePlugin, m_devicePlugins) {
if (devicePlugin->requiredHardware().testFlag(HardwareResource::TypeBluetoothLE) && devicePlugin->pluginId() == pluginId) {
devicePlugin->bluetoothDiscoveryFinished(deviceInfos);
}
}
}
//void DeviceManager::bluetoothDiscoveryFinished(const PluginId &pluginId, const QList<QBluetoothDeviceInfo> &deviceInfos)
//{
// foreach (DevicePlugin *devicePlugin, m_devicePlugins) {
// if (devicePlugin->requiredHardware().testFlag(HardwareResource::TypeBluetoothLE) && devicePlugin->pluginId() == pluginId) {
// devicePlugin->bluetoothDiscoveryFinished(deviceInfos);
// }
// }
//}
void DeviceManager::timerEvent()
{

View File

@ -165,13 +165,14 @@ private slots:
// Only connect this to Devices. It will query the sender()
void slotDeviceStateValueChanged(const QUuid &stateTypeId, const QVariant &value);
void radio433SignalReceived(QList<int> rawData);
void replyReady(const PluginId &pluginId, QNetworkReply *reply);
// void radio433SignalReceived(QList<int> rawData);
void upnpDiscoveryFinished(const QList<UpnpDeviceDescriptor> &deviceDescriptorList, const PluginId &pluginId);
void upnpNotifyReceived(const QByteArray &notifyData);
// void replyReady(const PluginId &pluginId, QNetworkReply *reply);
void bluetoothDiscoveryFinished(const PluginId &pluginId, const QList<QBluetoothDeviceInfo> &deviceInfos);
// void upnpDiscoveryFinished(const QList<UpnpDeviceDescriptor> &deviceDescriptorList, const PluginId &pluginId);
// void upnpNotifyReceived(const QByteArray &notifyData);
// void bluetoothDiscoveryFinished(const PluginId &pluginId, const QList<QBluetoothDeviceInfo> &deviceInfos);
void timerEvent();
@ -196,15 +197,6 @@ private:
QList<DevicePlugin *> m_pluginTimerUsers;
HardwareManager *m_hardwareManager;
// // Hardware Resources
// Radio433 *m_radio433;
// PluginTimer *m_pluginTimer;
// NetworkAccessManager *m_networkManager;
// UpnpDiscovery *m_upnpDiscovery;
// QtAvahiServiceBrowser *m_avahiBrowser;
// BluetoothScanner *m_bluetoothScanner;
QHash<QUuid, DevicePairingInfo> m_pairingsJustAdd;
QHash<QUuid, DevicePairingInfo> m_pairingsDiscovery;

View File

@ -56,24 +56,14 @@
/*! Construct the hardware resource Radio433 with the given \a parent. Each possible 433 MHz hardware will be initialized here. */
Radio433::Radio433(QObject *parent) :
HardwareResource(HardwareResource::TypeRadio433, parent)
HardwareResource(HardwareResource::TypeRadio433, "Radio 433 MHz", parent)
{
GuhSettings settings(GuhSettings::SettingsRoleGlobal);
qCDebug(dcHardware) << "Loading GPIO settings from:" << settings.fileName();
settings.beginGroup("RF433");
int transmitterGpioNumber = settings.value("rf433tx",22).toInt();
settings.endGroup();
m_transmitter = new Radio433Trasmitter(this, transmitterGpioNumber);
m_brennenstuhlTransmitter = new Radio433BrennenstuhlGateway(this);
connect(m_brennenstuhlTransmitter, &Radio433BrennenstuhlGateway::availableChanged, this, &Radio433::brennenstuhlAvailableChanged);
}
/*! Destroys the hardware resource Radio433 object. */
Radio433::~Radio433()
{
m_transmitter->quit();
setAvailable(false);
qCDebug(dcHardware()) << "-->" << name() << "created successfully.";
}
/*! Enables GPIO transmitter and receiver and the Brennenstuhl Lan Gateway.
@ -81,22 +71,7 @@ Radio433::~Radio433()
bool Radio433::enable()
{
m_brennenstuhlTransmitter->enable();
// check if GPIOs are available
if (Gpio::isAvailable()) {
bool transmitterAvailable = m_transmitter->startTransmitter();
if (!transmitterAvailable) {
//qCWarning(dcHardware) << "ERROR: radio 433 MHz transmitter not available on GPIO's";
}
if (!transmitterAvailable) {
qCWarning(dcHardware) << "--> Radio 433 MHz GPIO's not available.";
return false;
}
}
setEnabled(true);
qCDebug(dcDeviceManager()) << "--> Radio 433 MHz GPIO's enabled.";
return true;
}
@ -111,26 +86,26 @@ bool Radio433::disable()
void Radio433::brennenstuhlAvailableChanged(const bool &available)
{
if (available) {
qCDebug(dcHardware()) << "--> Radio 433 MHz Brennenstuhl LAN Gateway available.";
qCDebug(dcHardware()) << name() << "Brennenstuhl LAN Gateway available.";
setAvailable(true);
} else {
qCWarning(dcHardware()) << "--> Radio 433 MHz Brennenstuhl LAN Gateway NOT available.";
qCWarning(dcHardware()) << name() << "Brennenstuhl LAN Gateway not available.";
setAvailable(false);
}
}
/*! Returns true, if the \a rawData with a certain \a delay (pulse length) could be sent \a repetitions times. */
bool Radio433::sendData(int delay, QList<int> rawData, int repetitions)
{
bool sendGpio = false;
bool sendBrennenstuhl = false;
if (m_brennenstuhlTransmitter->available()) {
sendBrennenstuhl = m_brennenstuhlTransmitter->sendData(delay, rawData, repetitions);
if (!available()) {
qCWarning(dcHardware()) << name() << "Brennenstuhl gateway not available";
return false;
}
if (m_transmitter->available()) {
m_transmitter->sendData(delay, rawData, repetitions);
sendGpio = true;
if (!enabled()) {
qCWarning(dcHardware()) << name() << "Hardware reouce disabled.";
return false;
}
return (sendGpio || sendBrennenstuhl);
return m_brennenstuhlTransmitter->sendData(delay, rawData, repetitions);
}

View File

@ -25,8 +25,6 @@
#include <QObject>
#include "radio433transmitter.h"
#include "libguh.h"
#include "hardwareresource.h"
#include "radio433brennenstuhlgateway.h"
@ -34,13 +32,11 @@
class LIBGUH_EXPORT Radio433 : public HardwareResource
{
Q_OBJECT
public:
explicit Radio433(QObject *parent = 0);
~Radio433();
friend class HardwareManager;
private:
Radio433Trasmitter *m_transmitter;
explicit Radio433(QObject *parent = 0);
Radio433BrennenstuhlGateway *m_brennenstuhlTransmitter;
private slots:

View File

@ -1,20 +1,34 @@
#include "hardwaremanager.h"
#include "plugintimer.h"
#include "bluetooth/bluetoothscanner.h"
#include "hardware/radio433/radio433.h"
#include "network/networkaccessmanager.h"
#include "network/upnp/upnpdiscovery.h"
#include "network/upnp/upnpdevicedescriptor.h"
#include "network/avahi/qtavahiservicebrowser.h"
HardwareManager::HardwareManager(QObject *parent) : QObject(parent)
{
// Init hardware resources
m_pluginTimer = new PluginTimer(10000, this);
m_hardwareResources.append(m_pluginTimer);
m_radio433 = new Radio433(this);
m_hardwareResources.append(m_radio433);
m_radio433->enable();
// Create network access manager for all resources, centralized
m_networkAccessManager = new QNetworkAccessManager(this);
// Note: configuration and proxy settings could be implemented here
// Network manager
m_networkManager = new NetworkAccessManager(this);
m_networkManager = new NetworkAccessManager(m_networkAccessManager, this);
m_hardwareResources.append(m_networkManager);
m_networkManager->enable();
// UPnP discovery
m_upnpDiscovery = new UpnpDiscovery(this);
m_upnpDiscovery = new UpnpDiscovery(m_networkAccessManager, this);
// Avahi Browser
m_avahiBrowser = new QtAvahiServiceBrowser(this);

View File

@ -2,17 +2,17 @@
#define HARDWAREMANAGER_H
#include <QObject>
#include <QNetworkAccessManager>
#include "plugintimer.h"
#include "bluetooth/bluetoothscanner.h"
#include "hardware/radio433/radio433.h"
#include "network/networkaccessmanager.h"
#include "network/upnp/upnpdiscovery.h"
#include "network/upnp/upnpdevicedescriptor.h"
#include "network/avahi/qtavahiservicebrowser.h"
#include "hardwareresource.h"
class PluginTimer;
class BluetoothScanner;
class Radio433;
class NetworkAccessManager;
class UpnpDiscovery;
class UpnpDeviceDescriptor;
class QtAvahiServiceBrowser;
class HardwareManager : public QObject
{
@ -33,6 +33,8 @@ public:
private:
QList<HardwareResource *> m_hardwareResources;
QNetworkAccessManager *m_networkAccessManager;
// Hardware Resources
Radio433 *m_radio433 = nullptr;
PluginTimer *m_pluginTimer = nullptr;

View File

@ -24,13 +24,19 @@
#include "guhsettings.h"
#include "hardwaremanager.h"
HardwareResource::HardwareResource(const Type &hardwareReourceType, QObject *parent) :
HardwareResource::HardwareResource(const Type &hardwareReourceType, const QString &name, QObject *parent) :
QObject(parent),
m_hardwareReourceType(hardwareReourceType)
m_hardwareReourceType(hardwareReourceType),
m_name(name)
{
// TODO: load if hardware resource is enabled or not
}
QString HardwareResource::name() const
{
return m_name;
}
bool HardwareResource::available() const
{
return m_available;

View File

@ -40,17 +40,21 @@ public:
Q_ENUM(Type)
Q_DECLARE_FLAGS(Types, Type)
explicit HardwareResource(const HardwareResource::Type &hardwareReourceType, QObject *parent = nullptr);
explicit HardwareResource(const HardwareResource::Type &hardwareReourceType, const QString &name, QObject *parent = nullptr);
HardwareResource::Type hardwareReourceType() const;
QString name() const;
bool available() const;
bool enabled() const;
HardwareResource::Type hardwareReourceType() const;
private:
HardwareResource::Type m_hardwareReourceType;
QString m_name;
bool m_available = false;
bool m_enabled = true;
HardwareResource::Type m_hardwareReourceType;
protected:
void setEnabled(const bool &enabled);

View File

@ -29,77 +29,82 @@
The network manager class is a reimplementation of the \l{http://doc-snapshot.qt-project.org/qt5-5.4/qnetworkaccessmanager.html}{QNetworkAccessManager}
and allows plugins to send network requests and receive replies.
*/
/*!
* \fn NetworkAccessManager::replyReady(const PluginId &pluginId, QNetworkReply *reply)
* This signal will be emitted whenever a pending network \a reply for the plugin with the given \a pluginId is finished.
*
* \sa DevicePlugin::networkManagerReplyReady()
*/
*/
#include "networkaccessmanager.h"
#include "loggingcategories.h"
/*! Construct the hardware resource NetworkAccessManager with the given \a parent. */
NetworkAccessManager::NetworkAccessManager(QObject *parent) :
QObject(parent)
NetworkAccessManager::NetworkAccessManager(QNetworkAccessManager *networkManager, QObject *parent) :
HardwareResource(HardwareResource::TypeNetworkManager, "Network access manager" , parent),
m_manager(networkManager)
{
m_manager = new QNetworkAccessManager(this);
connect(m_manager, &QNetworkAccessManager::finished, this, &NetworkAccessManager::replyFinished);
setAvailable(true);
qCDebug(dcDeviceManager) << "--> Network manager created successfully.";
qCDebug(dcHardware()) << "-->" << name() << "created successfully.";
}
/*! Posts a request to obtain the contents of the target \a request from the plugin with the given \a pluginId
* and returns a new QNetworkReply object opened for reading which emits the replyReady() signal whenever new
* data arrives.
* The contents as well as associated headers will be downloaded.
*
* \note The plugin has to delete the QNetworkReply with the function deleteLater().
*
* \sa DevicePlugin::networkManagerGet()
*/
QNetworkReply *NetworkAccessManager::get(const PluginId &pluginId, const QNetworkRequest &request)
QNetworkReply *NetworkAccessManager::get(const QNetworkRequest &request)
{
QNetworkReply *reply = m_manager->get(request);
m_replies.insert(reply, pluginId);
return reply;
return m_manager->get(request);
}
/*! Sends an HTTP POST request to the destination specified by \a request from the plugin with the given
* \a pluginId and returns a new QNetworkReply object opened for reading that will contain the reply sent
* by the server. The contents of the \a data will be uploaded to the server.
*
* \note The plugin has to delete the QNetworkReply with the function deleteLater().
*
* \sa DevicePlugin::networkManagerPost()
*/
QNetworkReply *NetworkAccessManager::post(const PluginId &pluginId, const QNetworkRequest &request, const QByteArray &data)
QNetworkReply *NetworkAccessManager::deleteResource(const QNetworkRequest &request)
{
QNetworkReply *reply = m_manager->post(request, data);
m_replies.insert(reply, pluginId);
return reply;
return m_manager->deleteResource(request);
}
/*! Uploads the contents of \a data to the destination \a request from the plugin with the given
* \a pluginId and returnes a new QNetworkReply object that will be open for reply.
*
* \note The plugin has to delete the QNetworkReply with the function deleteLater().
*
* \sa DevicePlugin::networkManagerPut()
*/
QNetworkReply *NetworkAccessManager::put(const PluginId &pluginId, const QNetworkRequest &request, const QByteArray &data)
QNetworkReply *NetworkAccessManager::head(const QNetworkRequest &request)
{
QNetworkReply *reply = m_manager->put(request, data);
m_replies.insert(reply, pluginId);
return reply;
return m_manager->head(request);
}
void NetworkAccessManager::replyFinished(QNetworkReply *reply)
QNetworkReply *NetworkAccessManager::post(const QNetworkRequest &request, QIODevice *data)
{
// NOTE: Each plugin has to delete his own replys with deleteLater()!!
// NOTE: also the reply->error() has to be handled in each plugin!!
PluginId pluginId = m_replies.take(reply);
emit replyReady(pluginId, reply);
return m_manager->post(request, data);
}
QNetworkReply *NetworkAccessManager::post(const QNetworkRequest &request, const QByteArray &data)
{
return m_manager->post(request, data);
}
QNetworkReply *NetworkAccessManager::post(const QNetworkRequest &request, QHttpMultiPart *multiPart)
{
return m_manager->post(request, multiPart);
}
QNetworkReply *NetworkAccessManager::put(const QNetworkRequest &request, QIODevice *data)
{
return m_manager->put(request, data);
}
QNetworkReply *NetworkAccessManager::put(const QNetworkRequest &request, const QByteArray &data)
{
return m_manager->post(request, data);
}
QNetworkReply *NetworkAccessManager::put(const QNetworkRequest &request, QHttpMultiPart *multiPart)
{
return m_manager->post(request, multiPart);
}
QNetworkReply *NetworkAccessManager::sendCustomRequest(const QNetworkRequest &request, const QByteArray &verb, QIODevice *data)
{
return m_manager->sendCustomRequest(request, verb, data);
}
bool NetworkAccessManager::enable()
{
m_manager->setNetworkAccessible(QNetworkAccessManager::Accessible);
setEnabled(true);
return true;
}
bool NetworkAccessManager::disable()
{
m_manager->setNetworkAccessible(QNetworkAccessManager::NotAccessible);
setEnabled(false);
return true;
}

View File

@ -25,6 +25,7 @@
#include "libguh.h"
#include "typeutils.h"
#include "hardwareresource.h"
#include <QObject>
#include <QNetworkAccessManager>
@ -33,25 +34,36 @@
#include <QDebug>
#include <QUrl>
class LIBGUH_EXPORT NetworkAccessManager : public QObject
class LIBGUH_EXPORT NetworkAccessManager : public HardwareResource
{
Q_OBJECT
public:
explicit NetworkAccessManager(QObject *parent = 0);
QNetworkReply *get(const PluginId &pluginId, const QNetworkRequest &request);
QNetworkReply *post(const PluginId &pluginId, const QNetworkRequest &request, const QByteArray &data);
QNetworkReply *put(const PluginId &pluginId, const QNetworkRequest &request, const QByteArray &data);
friend class HardwareManager;
public:
// Note: only these methods are allowed from a plugin perspective
QNetworkReply *get(const QNetworkRequest &request);
QNetworkReply *deleteResource(const QNetworkRequest &request);
QNetworkReply *head(const QNetworkRequest &request);
QNetworkReply *post(const QNetworkRequest &request, QIODevice *data);
QNetworkReply *post(const QNetworkRequest &request, const QByteArray &data);
QNetworkReply *post(const QNetworkRequest &request, QHttpMultiPart *multiPart);
QNetworkReply *put(const QNetworkRequest &request, QIODevice *data);
QNetworkReply *put(const QNetworkRequest &request, const QByteArray &data);
QNetworkReply *put(const QNetworkRequest &request, QHttpMultiPart *multiPart);
QNetworkReply *sendCustomRequest(const QNetworkRequest &request, const QByteArray &verb, QIODevice *data = nullptr);
private:
// Note: only the HardwareManager is allowed to create this resource
NetworkAccessManager(QNetworkAccessManager *networkManager, QObject *parent = 0);
QNetworkAccessManager *m_manager;
QHash<QNetworkReply *, PluginId> m_replies;
signals:
void replyReady(const PluginId &pluginId, QNetworkReply *reply);
private slots:
void replyFinished(QNetworkReply *reply);
public slots:
bool enable();
bool disable();
};

View File

@ -57,44 +57,17 @@
#include <QXmlStreamWriter>
/*! Construct the hardware resource UpnpDiscovery with the given \a parent. */
UpnpDiscovery::UpnpDiscovery(QObject *parent) :
QUdpSocket(parent)
UpnpDiscovery::UpnpDiscovery(QNetworkAccessManager *networkAccessManager, QObject *parent) :
HardwareResource(HardwareResource::TypeUpnpDisovery, "UPnP discovery", parent),
m_networkAccessManager(networkAccessManager)
{
// 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)){
qCWarning(dcHardware) << "UPnP discovery could not bind to port" << m_port;
return;
}
if(!joinMulticastGroup(m_host)){
qCWarning(dcHardware) << "UPnP discovery could not join multicast group" << m_host;
return;
}
// network access manager for requesting device information
m_networkAccessManager = new QNetworkAccessManager(this);
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);
m_notificationTimer = new QTimer(this);
m_notificationTimer->setInterval(30000);
m_notificationTimer->setSingleShot(false);
connect(m_notificationTimer, &QTimer::timeout, this, &UpnpDiscovery::notificationTimeout);
m_notificationTimer->start();
qCDebug(dcDeviceManager) << "--> UPnP discovery created successfully.";
sendAliveMessage();
sendAliveMessage();
setAvailable(true);
qCDebug(dcDeviceManager) << "-->" << name() << "created successfully.";
}
/*! Destruct this \l{UpnpDiscovery} object. */
@ -102,20 +75,20 @@ UpnpDiscovery::~UpnpDiscovery()
{
qCDebug(dcApplication) << "Shutting down \"UPnP Server\"";
sendByeByeMessage();
waitForBytesWritten();
close();
m_socket->waitForBytesWritten();
m_socket->close();
}
/*! Returns false, if the \l{UpnpDiscovery} resource is not available. Returns true, if a device with
* the given \a searchTarget, \a userAgent and \a pluginId can be discovered.*/
bool UpnpDiscovery::discoverDevices(const QString &searchTarget, const QString &userAgent, const PluginId &pluginId)
{
if(state() != BoundState){
if(m_socket->state() != QUdpSocket::BoundState){
qCWarning(dcHardware) << "UPnP not bound to port 1900";
return false;
}
qCDebug(dcHardware) << "UPnP: discover" << searchTarget << userAgent;
qCDebug(dcHardware) << name() << "discover" << searchTarget << userAgent;
// create a new request
UpnpDiscoveryRequest *request = new UpnpDiscoveryRequest(this, pluginId, searchTarget, userAgent);
@ -129,8 +102,7 @@ bool UpnpDiscovery::discoverDevices(const QString &searchTarget, const QString &
void UpnpDiscovery::requestDeviceInformation(const QNetworkRequest &networkRequest, const UpnpDeviceDescriptor &upnpDeviceDescriptor)
{
QNetworkReply *replay;
replay = m_networkAccessManager->get(networkRequest);
QNetworkReply *replay = m_networkAccessManager->get(networkRequest);
m_informationRequestList.insert(replay, upnpDeviceDescriptor);
}
@ -187,7 +159,7 @@ void UpnpDiscovery::respondToSearchRequest(QHostAddress host, int port)
"\r\n");
//qCDebug(dcHardware) << QString("Sending response to %1:%2\n").arg(host.toString()).arg(port);
writeDatagram(rootdeviceResponseMessage, host, port);
m_socket->writeDatagram(rootdeviceResponseMessage, host, port);
}
}
}
@ -197,12 +169,12 @@ void UpnpDiscovery::respondToSearchRequest(QHostAddress host, int port)
/*! This method will be called to send the SSDP message \a data to the UPnP multicast.*/
void UpnpDiscovery::sendToMulticast(const QByteArray &data)
{
writeDatagram(data, m_host, m_port);
m_socket->writeDatagram(data, m_host, m_port);
}
void UpnpDiscovery::error(QAbstractSocket::SocketError error)
{
qCWarning(dcHardware) << "UPnP socket error:" << error << errorString();
qCWarning(dcHardware) << "UPnP socket error:" << error << m_socket->errorString();
}
void UpnpDiscovery::readData()
@ -213,9 +185,9 @@ void UpnpDiscovery::readData()
QUrl location;
// read the answere from the multicast
while (hasPendingDatagrams()) {
data.resize(pendingDatagramSize());
readDatagram(data.data(), data.size(), &hostAddress, &port);
while (m_socket->hasPendingDatagrams()) {
data.resize(m_socket->pendingDatagramSize());
m_socket->readDatagram(data.data(), data.size(), &hostAddress, &port);
}
if (data.contains("M-SEARCH") && !QNetworkInterface::allAddresses().contains(hostAddress)) {
@ -434,3 +406,52 @@ void UpnpDiscovery::discoverTimeout()
m_discoverRequests.removeOne(discoveryRequest);
delete discoveryRequest;
}
bool UpnpDiscovery::enable()
{
// Clean up
if (m_socket) {
delete m_socket;
m_socket = nullptr;
}
// Bind udp socket and join multicast group
m_socket = new QUdpSocket(this);
m_port = 1900;
m_host = QHostAddress("239.255.255.250");
m_socket->setSocketOption(QAbstractSocket::MulticastTtlOption,QVariant(1));
m_socket->setSocketOption(QAbstractSocket::MulticastLoopbackOption,QVariant(1));
if(!m_socket->bind(QHostAddress::AnyIPv4, m_port, QUdpSocket::ShareAddress)){
qCWarning(dcHardware()) << name() << "could not bind to port" << m_port;
delete m_socket;
m_socket = nullptr;
return false;
}
if(!m_socket->joinMulticastGroup(m_host)){
qCWarning(dcHardware()) << name() << "could not join multicast group" << m_host;
delete m_socket;
m_socket = nullptr;
return false;
}
connect(m_socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(error(QAbstractSocket::SocketError)));
connect(m_socket, &QUdpSocket::readyRead, this, &UpnpDiscovery::readData);
m_notificationTimer->start();
sendAliveMessage();
sendAliveMessage();
setEnabled(true);
return true;
}
bool UpnpDiscovery::disable()
{
// TODO:
setEnabled(false);
return true;
}

View File

@ -31,33 +31,38 @@
#include <QNetworkRequest>
#include <QUrl>
#include "libguh.h"
#include "devicemanager.h"
#include "hardwareresource.h"
#include "upnpdiscoveryrequest.h"
#include "upnpdevicedescriptor.h"
#include "devicemanager.h"
#include "libguh.h"
// Discovering UPnP devices reference: http://upnp.org/specs/arch/UPnP-arch-DeviceArchitecture-v1.1.pdf
// guh basic device reference: http://upnp.org/specs/basic/UPnP-basic-Basic-v1-Device.pdf
class UpnpDiscoveryRequest;
class LIBGUH_EXPORT UpnpDiscovery : public QUdpSocket
class LIBGUH_EXPORT UpnpDiscovery : public HardwareResource
{
Q_OBJECT
public:
explicit UpnpDiscovery(QObject *parent = 0);
~UpnpDiscovery();
friend class HardwareManager;
public:
bool discoverDevices(const QString &searchTarget = "ssdp:all", const QString &userAgent = "", const PluginId &pluginId = PluginId());
void sendToMulticast(const QByteArray &data);
private:
explicit UpnpDiscovery(QNetworkAccessManager *networkAccessManager, QObject *parent = 0);
~UpnpDiscovery();
QUdpSocket *m_socket = nullptr;
QHostAddress m_host;
qint16 m_port;
QTimer *m_notificationTimer;
QTimer *m_notificationTimer = nullptr;
QNetworkAccessManager *m_networkAccessManager;
QNetworkAccessManager *m_networkAccessManager = nullptr;
QList<UpnpDiscoveryRequest *> m_discoverRequests;
QHash<QNetworkReply*,UpnpDeviceDescriptor> m_informationRequestList;
@ -77,6 +82,10 @@ private slots:
void sendByeByeMessage();
void sendAliveMessage();
void discoverTimeout();
public slots:
bool enable();
bool disable();
};
#endif // UPNPDISCOVERY_H

View File

@ -148,6 +148,7 @@
#include "devicemanager.h"
#include "guhsettings.h"
#include "bluetooth/bluetoothscanner.h"
#include "hardware/radio433/radio433.h"
#include "network/upnp/upnpdiscovery.h"
@ -541,56 +542,6 @@ bool DevicePlugin::transmitData(int delay, QList<int> rawData, int repetitions)
}
return false;
}
/*! Posts a request to obtain the contents of the target \a request and returns a new QNetworkReply object
* opened for reading which emits the replyReady() signal whenever new data arrives.
* The contents as well as associated headers will be downloaded.
*
* \note The plugin has to delete the QNetworkReply with the function deleteLater().
*
* \sa NetworkAccessManager::get()
*/
QNetworkReply *DevicePlugin::networkManagerGet(const QNetworkRequest &request)
{
if (requiredHardware().testFlag(HardwareResource::TypeNetworkManager)) {
return deviceManager()->m_hardwareManager->networkManager()->get(pluginId(), request);
} else {
qCWarning(dcDeviceManager) << "Network manager hardware resource not set for plugin" << pluginName();
}
return nullptr;
}
/*! Sends an HTTP POST request to the destination specified by \a request and returns a new QNetworkReply object
* opened for reading that will contain the reply sent by the server. The contents of the \a data will be
* uploaded to the server.
*
* \note The plugin has to delete the QNetworkReply with the function deleteLater().
*
* \sa NetworkAccessManager::post()
*/
QNetworkReply *DevicePlugin::networkManagerPost(const QNetworkRequest &request, const QByteArray &data)
{
if (requiredHardware().testFlag(HardwareResource::TypeNetworkManager)) {
return deviceManager()->m_hardwareManager->networkManager()->post(pluginId(), request, data);
} else {
qCWarning(dcDeviceManager) << "Network manager hardware resource not set for plugin" << pluginName();
}
return nullptr;
}
/*! Uploads the contents of \a data to the destination \a request and returnes a new QNetworkReply object that will be open for reply.
*
* \note The plugin has to delete the QNetworkReply with the function deleteLater().
*
* \sa NetworkAccessManager::put()
*/
QNetworkReply *DevicePlugin::networkManagerPut(const QNetworkRequest &request, const QByteArray &data)
{
if (requiredHardware().testFlag(HardwareResource::TypeNetworkManager)) {
return deviceManager()->m_hardwareManager->networkManager()->put(pluginId(), request, data);
} else {
qCWarning(dcDeviceManager) << "Network manager hardware resource not set for plugin" << pluginName();
}
return nullptr;
}
void DevicePlugin::setMetaData(const QJsonObject &metaData)
{

View File

@ -119,11 +119,6 @@ protected:
// Bluetooth LE discovery
bool discoverBluetooth();
// Network manager
QNetworkReply *networkManagerGet(const QNetworkRequest &request);
QNetworkReply *networkManagerPost(const QNetworkRequest &request, const QByteArray &data);
QNetworkReply *networkManagerPut(const QNetworkRequest &request, const QByteArray &data);
private:
void setMetaData(const QJsonObject &metaData);
void loadMetaData();

View File

@ -1,7 +1,8 @@
#include "plugintimer.h"
#include "loggingcategories.h"
PluginTimer::PluginTimer(int intervall, QObject *parent) :
HardwareResource(HardwareResource::TypeTimer, parent),
HardwareResource(HardwareResource::TypeTimer, "Plugin timer", parent),
m_intervall(intervall)
{
// FIXME: the timer should be able to emit timerEvents with different resolutions
@ -11,6 +12,8 @@ PluginTimer::PluginTimer(int intervall, QObject *parent) :
connect(m_timer, &QTimer::timeout, this, &PluginTimer::timerEvent);
setAvailable(true);
qCDebug(dcHardware()) << "-->" << name() << "created successfully.";
}
bool PluginTimer::enable()